setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesesetup
安装配置
End-to-end install and first-run setup for a Coder deployment without
opening the Coder web UI.
The web UI works fine. This skill exists so the user can run one
scripted, repeatable, CLI-only path: install, start the server,
bootstrap the admin user, push a starter template, optionally
create a workspace, and surface the credentials. It is the right
path for demos, headless boxes, automation, team rollouts, and
anyone who explicitly says they don't want to touch the UI.
无需打开Coder Web UI,即可完成Coder部署的端到端安装和首次运行配置。
Web UI本身运行良好,但该技能的存在是为了让用户能够通过一条可脚本化、可重复的纯CLI路径完成操作:安装、启动服务器、引导管理员用户、推送入门模板、(可选)创建工作区,并展示凭据。这适用于演示、无界面主机、自动化、团队部署,以及明确表示不想使用UI的用户。
Where to get authoritative information
权威信息来源
Anything topic-specific (OIDC, custom GitHub OAuth, GitLab,
external provisioners, wildcard URL, TLS termination, template
authoring, cloud installs, Kubernetes / Helm values, Rancher,
OpenShift, air-gapped, upgrades, backups, telemetry, Premium
features) lives in the upstream docs. Pull from there instead of
guessing or duplicating. The docs publish a machine-readable
index designed for agents:
- https://coder.com/docs/llms.txt -- compact index. Every page
is also available as raw Markdown by appending to its URL or sending
.md. Read this once at the start of the install to see what's available.Accept: text/markdown - https://coder.com/docs/llms-full.txt -- the full corpus in one file when the user asks something the index alone can't answer.
This skill only documents the install workflow itself: the order
of phases, the user-facing question wording, the small number of
quirks that aren't on coder.com (the auto-tunnel URL parsing
recipe, the GitHub device-flow callback recipe, the workspace
host guard). For everything else, point the user at the relevant
page and let them or a follow-up agent
configure it. That keeps the skill from drifting out of date.
coder.com/docs/...md任何特定主题(OIDC、自定义GitHub OAuth、GitLab、外部置备器、通配符URL、TLS终止、模板编写、云安装、Kubernetes/Helm配置、Rancher、OpenShift、离线环境、升级、备份、遥测、高级功能)的信息都存在于上游文档中。请直接引用这些文档,不要猜测或重复内容。文档发布了专为Agent设计的机器可读索引:
- https://coder.com/docs/llms.txt -- 精简索引。每个页面也可以通过在URL后添加或发送
.md获取原始Markdown格式内容。在安装开始时读取一次该文件,了解可用内容。Accept: text/markdown - https://coder.com/docs/llms-full.txt -- 当用户的问题无法仅通过索引解答时,可查看该完整语料文件。
本技能仅记录安装工作流本身:阶段顺序、面向用户的问题措辞、少数未在coder.com上记录的细节(自动隧道URL解析方案、GitHub设备流回调方案、工作区主机防护)。其他所有内容,请引导用户查看相关的页面,由后续Agent进行配置。这样可避免技能内容过时。
coder.com/docs/...mdTalking to the user
与用户沟通的原则
Assume the user has never used Coder and does not know what a
template, workspace, agent, provisioner, access URL, wildcard
URL, or external auth provider is. They asked you to install
Coder; they did not ask for a tour of its internals. Run the
install for them.
Hard rules for every message you send the user:
- No flags, env-var names, or config keys in user-facing
questions. ,
--first-user-trial,CODER_ACCESS_URL, andCODER_WILDCARD_ACCESS_URLare internal details. They can appear in commands you run, and in the final summary as paths to files you wrote, but not as things the user has to understand.CODER_EXTERNAL_AUTH_* - Explain the thing before you name it. If you must use a Coder term, say what it does first in one short sentence, then use the term. Example: "a starter project that builds workspaces (Coder calls this a template)".
- Ask one short choice at a time. Never present a decision matrix.
- Default aggressively. Pick the obvious default and ask the user to confirm, instead of making them choose from options.
- Translate errors. Don't paste raw server logs at the user. Read the log yourself, decide what's wrong, and tell them in plain English. Show the raw log only if they ask.
- No "Coder-ese" in the final summary. The handoff at the end is what the user reads first. Use "sign-in page", "the app you can open in a browser", "the example project", not "access URL", "dashboard", "template".
- Do not narrate yourself. The user does not know or care that a "skill" exists. Never say "this skill", "the setup skill", "I ran the skill", "I used the skill", or similar. When you need to refer to what just happened, say "I installed Coder", "the install", or "setup". The handoff messages and any error explanations follow this rule too.
- Pick exactly one option in any user-facing template. When
the skill text shows alternatives like
, that notation is for you, not the user. Resolve it to the single command that matches how Coder is actually running before you show anything to the user. Never paste the alternatives literally.
<one of: tail -f ... | docker compose logs -f ...> - Do not point the user at pages or any documentation URL in user-facing text. Those
coder.com/docs/*.mdpages exist so the agent (you) can read them and apply the guidance. The user installed Coder so an agent would do this work for them; sending them a doc link is telling them to go read the manual instead. The only URLs that belong in chat are concrete user destinations (the deployment's access URL,.mdfor license signup, similar). Documentation reading is yours, not theirs.coder.com/trial - Do not hand the user a CLI walkthrough as "what to try
next." Lines like ,
coder templates init,coder templates push,coder ssh <name>are things the agent runs, not things the user has to learn. If the user might want one of those actions, offer to do it for them in plain English ("want me to add a different starter?" / "want me to wire up Okta sign-in?") and run it when they say yes. The point of the skill is that the user doesn't have to type these commands.coder licenses add
A short concept glossary you can pull plain-English phrases from:
- Coder -> "a thing that gives you and your team cloud development environments you open in the browser or in your editor".
- Access URL -> "the web address people will open to use Coder".
- Wildcard URL -> "a DNS setup that lets apps inside your dev environment have their own subdomain".
- Workspace -> "a single dev environment for one person".
- Template -> "a recipe Coder follows when it builds a workspace; e.g. 'one Linux container with VS Code'".
- Agent / Provisioner -> internals; users normally don't need to know they exist.
- External auth -> "letting workspaces sign in to GitHub / GitLab / etc. so they can clone private repos".
- Owner -> "the admin account; the first person to sign in becomes one automatically".
- Free vs paid -> Coder is open source; nothing the skill
does costs money. The upstream CLI has a flag that turns on a 30-day enterprise-feature evaluation; the skill always passes
--first-user-trialand does not bring it up.--first-user-trial=false
If the user asks for technical detail ("what flag does that map
to?", "show me the env var"), shift to engineer voice for that
one answer; default back to plain English on the next turn.
假设用户从未使用过Coder,也不了解template(模板)、workspace(工作区)、agent(代理)、provisioner(置备器)、access URL(访问URL)、wildcard URL(通配符URL)或external auth provider(外部认证提供商)等概念。用户要求的是安装Coder,而不是了解其内部机制。直接为用户完成安装即可。
发送给用户的每条消息必须遵守以下严格规则:
- 用户问题中不得出现命令行参数、环境变量名或配置键。、
--first-user-trial、CODER_ACCESS_URL和CODER_WILDCARD_ACCESS_URL均为内部细节。它们可以出现在你执行的命令中,或在最终摘要中作为你写入的文件路径,但不得作为需要用户理解的内容呈现。CODER_EXTERNAL_AUTH_* - 先解释概念,再提及术语。如果必须使用Coder特定术语,先用简短的一句话说明其功能,再使用该术语。示例:"一个用于构建工作区的入门项目(Coder称之为template)"。
- 一次只提出一个简短的选择问题。绝不要呈现决策矩阵。
- 主动设置默认选项。选择明显的默认选项并请求用户确认,而非让用户从多个选项中选择。
- 翻译错误信息。不要将原始服务器日志直接粘贴给用户。自行读取日志,判断问题所在,并用通俗易懂的语言告知用户。仅在用户要求时才展示原始日志。
- 最终摘要中不得使用Coder专属术语。最后的交接内容是用户首先会阅读的部分。使用"登录页面"、"可在浏览器中打开的应用"、"示例项目"等表述,而非"access URL"、"dashboard"、"template"。
- 不要提及技能本身。用户不知道也不关心"skill"的存在。绝不要说"这个技能"、"安装技能"、"我运行了该技能"或类似表述。当需要指代刚刚完成的操作时,使用"我安装了Coder"、"安装过程"或"配置"。交接消息和任何错误解释也需遵循此规则。
- 在面向用户的模板中仅选择一个选项。当技能文本中出现类似的替代选项时,该符号是给你的提示,而非呈现给用户的内容。在展示给用户之前,将其解析为与Coder实际运行方式匹配的单一命令。绝不要直接粘贴替代选项。
<one of: tail -f ... | docker compose logs -f ...> - 不要在面向用户的文本中引导用户访问页面或任何文档URL。这些
coder.com/docs/*.md页面是供Agent(你)阅读并应用指导的。用户安装Coder是为了让Agent代劳这些工作;发送文档链接相当于让用户自己去阅读手册,违背了安装该技能的初衷。聊天中仅应包含具体的用户目标链接(部署的访问URL、用于许可证注册的.md等类似链接)。阅读文档是你的工作,而非用户的。coder.com/trial - 不要将CLI操作指南作为"下一步尝试"交给用户。、
coder templates init、coder templates push、coder ssh <name>等命令是Agent执行的操作,而非用户需要学习的内容。如果用户可能需要其中某项操作,用通俗易懂的语言主动提出("需要我添加一个不同的入门模板吗?" / "需要我配置Okta登录吗?"),并在用户同意后执行。该技能的核心价值在于用户无需输入这些命令。coder licenses add
以下是一个简短的术语表,你可以从中提取通俗易懂的表述:
- Coder -> "一款为你和你的团队提供可在浏览器或编辑器中打开的云开发环境的工具"。
- Access URL -> "用户将打开以使用Coder的网址"。
- Wildcard URL -> "一种DNS配置,允许开发环境中的应用拥有自己的子域名"。
- Workspace -> "供单人使用的独立开发环境"。
- Template -> "Coder构建工作区时遵循的配置模板;例如'带有VS Code的Linux容器'"。
- Agent / Provisioner -> 内部组件;用户通常无需了解它们的存在。
- External auth -> "允许工作区登录到GitHub/GitLab等平台,以便克隆私有仓库"。
- Owner -> "管理员账号;首个登录的用户将自动成为管理员"。
- 免费版 vs 付费版 -> Coder是开源软件;本技能执行的所有操作均无需付费。上游CLI有一个参数可开启30天企业功能试用;本技能始终传递
--first-user-trial,且不会提及该参数。--first-user-trial=false
如果用户询问技术细节("这对应哪个参数?"、"展示环境变量"),可在该次回答中切换为工程师口吻;后续回复默认回到通俗易懂的语言。
Workflow
工作流
Each phase has a clear exit criterion. Confirm before any
destructive action (system package install, opening ports,
overwriting kubeconfigs, deleting volumes).
每个阶段都有明确的退出标准。在执行任何破坏性操作(系统包安装、开放端口、覆盖kubeconfig、删除卷)前需确认。
Move quickly
快速推进
Users expect this install to feel fast, not deliberate. Keep
your tool calls economical:
-
Don't read reference files you don't need. Three exist:
- is only relevant when Phase 4 takes the GitHub device-code path; the protocol is summarized at the call site and the steps are real bundled scripts under
references/first-user-github-device.md. Read the reference only when something fails and the failure mode isn't already covered in Phase 4.scripts/ - is only relevant when the Phase 7 user accepts the Coder Agents offer. Read it then, not before. If they decline, skip the file entirely.
references/coder-agents.md - is only relevant when something is actually stalled (see the bullet below).
references/troubleshooting.md
Reading any of those proactively to "refresh" wastes a multi-thousand-token tool call the user is waiting on. -
Don't run probes you don't need. The host probe in Phase 1 exists to fill in defaults; if the user already answered the five core questions, you don't need to detect the package manager or the distro version.
-
Combine related shell into one tool call. A short multi-line block () is one round trip; the same three operations as three separate tool calls is three round trips of latency. The exception is the GitHub device flow, which must stay split for the reason documented at the Phase 4 call site.
mkdir; curl; verify -
Stream long-running commands instead of waiting on their full output.,
coder server, andcoder templates pushall take a while; tail their logs from a state-dir file rather than blocking the chat on their stdout.coder create -
When something stalls (server won't come up, provisioner can't reach Docker, certificates won't issue, the apex doesn't resolve), checkbefore you start diagnosing from scratch. The five recurring failure modes documented there (embedded Postgres on ARM, bundled Terraform's PGP key, fresh Docker group not picked up by the running server, Caddy redirect loops, home-router rebind protection) are not in upstream docs and have known fixes.
references/troubleshooting.md
- Discover. Ask the user a small set of questions in plain English. Probe the host afterward to fill in defaults.
- Install. Use (or Helm / compose).
install.sh - Start. Run the server.
- Sign in. Make the asking user the admin (Owner).
- Template. Push a starter that matches the chosen infrastructure.
- Workspace (optional). Build the first dev environment.
- Hand off. Tell the user how to sign in, how to start / stop, and where to go next.
External-services configuration (custom OAuth, GitLab / GHES,
external provisioners, wildcard DNS, OIDC) is intentionally not
its own phase here. Fresh deployments work without any of it; if
the user asks for one of those features, follow the matching
page on coder.com/docs and apply it.
用户期望安装过程快速,而非拖沓。请高效地执行工具调用:
-
不要读取不需要的参考文件。共有三个参考文件:
- 仅在阶段4采用GitHub设备码路径时相关;协议在调用点已总结,步骤在
references/first-user-github-device.md下的捆绑脚本中实现。仅当出现故障且故障模式未在阶段4中覆盖时,才读取该参考文件。scripts/ - 仅在阶段7用户接受Coder Agents提议时相关。仅在此时读取该文件;如果用户拒绝,则完全跳过。
references/coder-agents.md - 仅在实际出现停滞情况时相关(见下方要点)。
references/troubleshooting.md
主动读取这些文件以"刷新"信息会浪费用户等待的数千token的工具调用资源。 -
不要运行不需要的探测命令。阶段1中的主机探测是为了填充默认值;如果用户已经回答了五个核心问题,则无需检测包管理器或发行版版本。
-
将相关的shell命令合并为一个工具调用。简短的多行命令块()只需一次往返;而将这三个操作分为三个单独的工具调用则会产生三次往返延迟。例外情况是GitHub设备流,必须按照阶段4调用点记录的原因拆分执行。
mkdir; curl; verify -
流式处理长时间运行的命令,而非等待其完整输出。、
coder server和coder templates push都需要较长时间;从状态目录文件中跟踪日志,而非阻塞聊天等待其标准输出。coder create -
当出现停滞情况(服务器无法启动、置备器无法连接Docker、证书无法颁发、 apex域名无法解析)时,先查看,再开始自行诊断。文档中记录的五个常见故障模式(ARM架构上的嵌入式Postgres、捆绑Terraform的PGP密钥、运行中的服务器未识别新的Docker组、Caddy重定向循环、家庭路由器的DNS rebind保护)未在上游文档中提及,但有已知的修复方案。
references/troubleshooting.md
- 发现阶段。用通俗易懂的语言向用户提出少量问题。之后探测主机以填充默认值。
- 安装阶段。使用(或Helm/compose)进行安装。
install.sh - 启动阶段。运行服务器。
- 登录阶段。让发起请求的用户成为管理员(Owner)。
- 模板阶段。推送与所选基础设施匹配的入门模板。
- 工作区阶段(可选)。构建首个开发环境。
- 交接阶段。告知用户如何登录、启动/停止服务,以及后续操作方向。
外部服务配置(自定义OAuth、GitLab/GHES、外部置备器、通配符DNS、OIDC)在此处未单独设为一个阶段。全新部署无需这些配置即可运行;如果用户要求其中某项功能,请遵循coder.com/docs上的对应页面进行配置。
Phase 1: Discover
阶段1:发现
Lead with the user. Walk away from this phase with the shortest
possible interview answered (familiarity, mode, infrastructure,
sign-in, dev environment) so Phases 2 onward have everything
they need.
Ask all five core questions up front using .
is the built-in Claude Code tool (v2.0.21+)
for structured multiple-choice prompts. Compared to plain text,
it renders as a real picker the user clicks through, captures
structured answers, and prevents the failure mode where the
agent asks two questions in chat and then silently guesses the
rest. Use it; do not paste the questions as a chat message.
AskUserQuestionAskUserQuestionAskUserQuestionCall 1. Four questions: familiarity, deployment mode,
infrastructure, sign-in.
json
{
"questions": [
{
"question": "Have you used Coder before?",
"header": "Familiarity",
"multiSelect": false,
"options": [
{"label": "First time", "description": "Never used Coder; explain concepts as we go."},
{"label": "Used it before", "description": "Skip the explanations; use Coder terms directly."}
]
},
{
"question": "Are you trying Coder out, or setting it up for your team long-term?",
"header": "Deployment mode",
"multiSelect": false,
"options": [
{"label": "Just trying it out", "description": "Quick-start on this machine; auto-tunnel URL."},
{"label": "For my team", "description": "Production: real domain, TLS, optional Postgres / OIDC."}
]
},
{
"question": "Where do you want Coder to run?",
"header": "Infrastructure",
"multiSelect": false,
"options": [
{"label": "Docker on this machine", "description": "Easiest if Docker is installed."},
{"label": "Kubernetes / Helm", "description": "Against a cluster you can reach with kubectl."},
{"label": "Directly on this machine", "description": "The binary, with systemd."},
{"label": "Something else", "description": "Rancher, OpenShift, AWS / GCP / Azure Marketplace, air-gapped."}
]
},
{
"question": "How do you want to sign in as the admin?",
"header": "Sign-in",
"multiSelect": false,
"options": [
{"label": "GitHub", "description": "I'll show you a short URL and a code; works from any phone."},
{"label": "Email and password", "description": "I'll generate a strong password and save it locally."}
]
}
]
}Call 2. One question: dev environment.
json
{
"questions": [
{
"question": "Want me to set up a starter dev environment and build the first one?",
"header": "Dev environment",
"multiSelect": false,
"options": [
{"label": "Yes, match my infrastructure", "description": "Linux container if Docker, Linux pod if Kubernetes."},
{"label": "Yes, a different kind", "description": "Tell me which (cloud VM, your own Terraform, etc.)."},
{"label": "Push the starter, but don't build a workspace yet", "description": "I'll do the first build myself."},
{"label": "Skip this entirely", "description": "Just install Coder; I'll add a template later."}
]
}
]
}Wait for each call's reply before sending the next; do not
batch the JSON yourself or paste it back as text.
If the runner does not expose (some
headless / setups, or runners that disabled it),
fall back to a single chat message with the five questions
verbatim, numbered, in this exact order:
AskUserQuestionclaude -pBefore I start, five quick questions:
- Have you used Coder before, or is this your first time?
- Are you trying Coder out on this machine, or setting it up for your team to use long-term?
- Where do you want Coder to run? Docker on this machine, Kubernetes / Helm against a cluster, directly on this machine (binary + systemd), or something else (Rancher, OpenShift, AWS / GCP / Azure, air-gapped)?
- For sign-in, GitHub (I'll show you a short URL and a code; works from any phone) or just create an email and password for you?
- After Coder is up, do you want me to push a starter dev environment and build the first one for you (default yes)? If you have a specific kind in mind, say so; otherwise I'll match what you picked in question 3.
Detect availability by attempting ; if the
runner reports it as unknown / unavailable, drop to the chat
fallback for the rest of Phase 1. Do not invent your own
text-only prompts when the tool is available; users have
reported the chat-message version of this interview as
significantly worse than the structured picker.
AskUserQuestionIf the user gives short or partial answers, accept them and
fill in defaults from the mapping tables below; never re-ask
an already-answered question.
After the answers come in:
- Map each answer using the tables in the per-question subsections below.
- Probe the host quietly (what package manager, is Docker installed, is there an existing Coder login, is this itself a Coder workspace).
- Show the user one short plan paragraph and get a single yes/no before doing anything destructive.
Do not run any of those probes before the questions. The user
should see a single batched question, not a screen of
/ / output
followed by partial questions.
uname -awhich dockercat /etc/os-releaseThe per-question subsections below describe how to map each
answer; they are not separate ask turns.
Hard guards run with the actions they protect, not in this phase:
- The workspace-host guard (don't install a host if this is itself someone's Coder workspace) runs at the start of Phase 2.
coder - The existing-login guard (only isolate when the host already has a Coder session pointing somewhere the user wouldn't want overwritten) runs at the start of Phase 4.
CODER_CONFIG_DIR
以用户为中心。通过最短的问答环节(熟悉度、模式、基础设施、登录方式、开发环境)完成该阶段,以便阶段2及后续阶段拥有所需的全部信息。
使用一次性提出所有五个核心问题。是Claude Code的内置工具(v2.0.21+),用于结构化的多项选择提示。与纯文本相比,它会呈现为用户可点击的选择器,捕获结构化答案,并避免Agent在聊天中提出两个问题后默默猜测其余答案的失败模式。请使用该工具;不要将问题作为聊天消息粘贴。
AskUserQuestionAskUserQuestionAskUserQuestion调用1。四个问题:熟悉度、部署模式、基础设施、登录方式。
json
{
"questions": [
{
"question": "Have you used Coder before?",
"header": "Familiarity",
"multiSelect": false,
"options": [
{"label": "First time", "description": "Never used Coder; explain concepts as we go."},
{"label": "Used it before", "description": "Skip the explanations; use Coder terms directly."}
]
},
{
"question": "Are you trying Coder out, or setting it up for your team long-term?",
"header": "Deployment mode",
"multiSelect": false,
"options": [
{"label": "Just trying it out", "description": "Quick-start on this machine; auto-tunnel URL."},
{"label": "For my team", "description": "Production: real domain, TLS, optional Postgres / OIDC."}
]
},
{
"question": "Where do you want Coder to run?",
"header": "Infrastructure",
"multiSelect": false,
"options": [
{"label": "Docker on this machine", "description": "Easiest if Docker is installed."},
{"label": "Kubernetes / Helm", "description": "Against a cluster you can reach with kubectl."},
{"label": "Directly on this machine", "description": "The binary, with systemd."},
{"label": "Something else", "description": "Rancher, OpenShift, AWS / GCP / Azure Marketplace, air-gapped."}
]
},
{
"question": "How do you want to sign in as the admin?",
"header": "Sign-in",
"multiSelect": false,
"options": [
{"label": "GitHub", "description": "I'll show you a short URL and a code; works from any phone."},
{"label": "Email and password", "description": "I'll generate a strong password and save it locally."}
]
}
]
}调用2。一个问题:开发环境。
json
{
"questions": [
{
"question": "Want me to set up a starter dev environment and build the first one?",
"header": "Dev environment",
"multiSelect": false,
"options": [
{"label": "Yes, match my infrastructure", "description": "Linux container if Docker, Linux pod if Kubernetes."},
{"label": "Yes, a different kind", "description": "Tell me which (cloud VM, your own Terraform, etc.)."},
{"label": "Push the starter, but don't build a workspace yet", "description": "I'll do the first build myself."},
{"label": "Skip this entirely", "description": "Just install Coder; I'll add a template later."}
]
}
]
}等待每次调用的回复后再发送下一个;不要自行批量处理JSON或作为文本粘贴回去。
如果运行环境未暴露(某些无界面/设置,或禁用了该工具的运行环境),则回退为单一聊天消息,按以下确切顺序列出五个问题:
AskUserQuestionclaude -p在开始之前,有五个快速问题:
- 你之前使用过Coder吗,还是第一次使用?
- 你是想在这台机器上试用Coder,还是为团队长期部署?
- 你希望Coder运行在哪里?这台机器上的Docker、Kubernetes/Helm集群、直接在这台机器上(二进制+systemd),还是其他环境(Rancher、OpenShift、AWS/GCP/Azure、离线环境)?
- 登录方式选择GitHub(我会展示一个短URL和验证码;任何手机均可使用)还是创建邮箱和密码?
- Coder启动后,需要我推送一个入门开发环境并为你构建第一个工作区吗(默认是)?如果你有特定需求,请说明;否则我会匹配你在问题3中选择的基础设施。
通过尝试调用来检测该工具是否可用;如果运行环境报告该工具未知/不可用,则在阶段1的剩余部分使用聊天回退方式。当工具可用时,不要自行发明纯文本提示;用户反馈聊天消息版本的问答体验远不如结构化选择器。
AskUserQuestion如果用户给出简短或部分答案,请接受并从下方映射表中填充默认值;绝不要重新询问已回答的问题。
收到答案后:
- 使用以下各问题小节中的表格映射每个答案。
- 静默探测主机(使用的包管理器、是否安装了Docker、是否存在现有Coder登录、当前是否为Coder工作区)。
- 向用户展示一段简短的计划说明,并在执行任何破坏性操作前获取单一的是/否确认。
在提问前不要运行任何探测命令。用户应看到一组批量问题,而非//的输出,然后是部分问题。
uname -awhich dockercat /etc/os-release以下各问题小节描述了如何映射每个答案;它们并非单独的提问环节。
严格的防护措施与它们所保护的操作一同执行,而非在本阶段:
- 工作区主机防护(如果当前环境本身是某个用户的Coder工作区,则不要安装主机版)在阶段2开始时执行。
coder - 现有登录防护(仅当主机已存在指向用户不希望被覆盖的Coder会话时,才隔离)在阶段4开始时执行。
CODER_CONFIG_DIR
Read the audience (question 1)
了解用户熟悉度(问题1)
This is question 1 in the call (or the
batched-five chat fallback); it is not a separate ask turn.
Use the answer to set the audience mode for the rest of the
install. Map the answer:
AskUserQuestion| What the user said | Mode |
|---|---|
| "first time", "new to Coder", "never used it", "just heard of it" | new |
| "used it", "have a deployment", "familiar", "upgrading", "moving" | familiar |
| anything ambiguous | new |
Default to new when in doubt. The cost of explaining a term
the user already knows is one extra sentence. The cost of
shipping jargon at someone who's never seen it is that they get
stuck.
What the modes change:
- new. Whenever you reach a Coder-specific concept (workspace, template, agent, provisioner, access URL, wildcard URL, external auth), pause for one sentence in plain English before using the word. Example: "Coder builds your dev environments from a recipe written in Terraform; we call those recipes templates. I'll push a starter template now." Don't belabor it; one sentence, then move on. When you mention Terraform, name it as "the language Terraform uses to describe cloud infrastructure" the first time. The glossary in the "Talking to the user" section is the source of phrasings.
- familiar. Skip the inline explanations. Use the Coder terms directly. Don't gloss "template" or "workspace".
Familiarity does not change the install path; it only changes
the narration. Quick-start vs production, Docker vs Kubernetes,
GitHub vs email, and every other technical decision is the same
either way.
If the user later asks "what's a template?" or "what's an
agent?", switch to new-mode for that turn regardless of what
they said earlier.
这是调用(或批量五个问题的聊天回退)中的问题1;并非单独的提问环节。根据答案设置后续安装的受众模式。映射答案:
AskUserQuestion| 用户表述 | 模式 |
|---|---|
| "first time"、"new to Coder"、"never used it"、"just heard of it" | 新手模式 |
| "used it"、"have a deployment"、"familiar"、"upgrading"、"moving" | 熟悉模式 |
| 任何模糊表述 | 新手模式 |
不确定时默认采用新手模式。向已了解术语的用户额外解释一次的成本只是多一句话;而向从未接触过的用户使用行话则会导致他们困惑。
模式差异:
- 新手模式。每当涉及Coder特定概念(工作区、模板、代理、置备器、访问URL、通配符URL、外部认证)时,先用通俗易懂的语言解释一句话,再使用术语。示例:"Coder使用Terraform编写的配置模板构建开发环境;我们将这些模板称为templates。我现在将推送一个入门模板。"不要过于冗长;一句话即可,然后继续。首次提及Terraform时,将其描述为"Terraform用于描述云基础设施的语言"。"与用户沟通的原则"部分的术语表是表述来源。
- 熟悉模式。跳过内联解释。直接使用Coder术语。无需解释"template"或"workspace"。
熟悉度不会改变安装路径;仅会改变叙述方式。快速启动vs生产环境、Docker vs Kubernetes、GitHub vs邮箱等所有技术决策在两种模式下均相同。
如果用户后续询问"什么是template?"或"什么是agent?",则在该次回复中切换为新手模式,无论之前的回答如何。
Pick the deployment mode (question 2)
选择部署模式(问题2)
This is question 2 in the call (or the
batched-five chat fallback). The answer drives almost every
later choice. Map it:
AskUserQuestion| What the user said | Mode |
|---|---|
| "trying it out", "demo", "play with it", "just me" | quick-start |
| "on this laptop", "my server", "throwaway" | quick-start |
Names a real domain ( | production |
| "HTTPS", "TLS", "Let's Encrypt", "behind a proxy" | production |
| "For my team", "for the company", "staging" | production |
| "Cloud workspaces" with a shared cloud account | production |
If signals conflict, ask one short follow-up. Don't guess.
If the user picks production, read
https://coder.com/docs/install.md and
https://coder.com/docs/admin/setup.md before proposing the plan
in step 6 below; the production install layout (managed Postgres,
TLS, Helm values, ingress) is documented there and changes more
often than this skill does.
这是调用(或批量五个问题的聊天回退)中的问题2。答案几乎决定了后续所有选择。映射答案:
AskUserQuestion| 用户表述 | 模式 |
|---|---|
| "trying it out"、"demo"、"play with it"、"just me" | 快速启动 |
| "on this laptop"、"my server"、"throwaway" | 快速启动 |
提及真实域名( | 生产环境 |
| "HTTPS"、"TLS"、"Let's Encrypt"、"behind a proxy" | 生产环境 |
| "For my team"、"for the company"、"staging" | 生产环境 |
| "Cloud workspaces"搭配共享云账户 | 生产环境 |
如果信号冲突,提出一个简短的跟进问题。不要猜测。
如果用户选择生产环境,请在提出步骤6中的计划前阅读https://coder.com/docs/install.md和https://coder.com/docs/admin/setup.md;生产环境的安装布局(托管Postgres、TLS、Helm配置、ingress)记录在这些文档中,且比本技能的更新频率更高。
Pick the infrastructure (question 3)
选择基础设施(问题3)
This is question 3 in the call (or the
batched-five chat fallback). Never silently default to Docker;
the answer must come from the user. Map it:
AskUserQuestion| User says | Install path |
|---|---|
| "Docker", "compose", "container" | Docker compose (Phase 2) |
| "Kubernetes", "Helm", "k8s", "kind" | Helm (Phase 2) |
| "directly", "on the host", "binary" | Standalone install via |
| "Rancher" / "OpenShift" | Hand off to https://coder.com/docs/install/rancher.md or |
| "AWS Marketplace" / "GCP" / "Azure" | Hand off to https://coder.com/docs/install/cloud.md |
| "Air-gapped", "offline", "no internet" | Hand off to https://coder.com/docs/install/airgap.md |
For the hand-off cases, do not try to drive the install yourself.
Tell the user the exact docs page, copy the salient command, and
stop.
If the user picks one of the three driveable options but doesn't
know which, look at the host (Phase 1 step 5) and recommend:
Docker if installed, else Kubernetes if has a current
context, else direct install. Confirm the recommendation in one
short sentence; don't lecture.
kubectl这是调用(或批量五个问题的聊天回退)中的问题3。绝不要默认选择Docker;答案必须来自用户。映射答案:
AskUserQuestion| 用户表述 | 安装路径 |
|---|---|
| "Docker"、"compose"、"container" | Docker compose(阶段2) |
| "Kubernetes"、"Helm"、"k8s"、"kind" | Helm(阶段2) |
| "directly"、"on the host"、"binary" | 通过 |
| "Rancher" / "OpenShift" | 引导至https://coder.com/docs/install/rancher.md或 |
| "AWS Marketplace" / "GCP" / "Azure" | 引导至https://coder.com/docs/install/cloud.md |
| "Air-gapped"、"offline"、"no internet" | 引导至https://coder.com/docs/install/airgap.md |
对于需要引导的情况,不要自行尝试完成安装。告知用户确切的文档页面,复制关键命令,然后停止操作。
如果用户选择了三个可自行驱动的选项之一但不确定具体选择,查看主机情况(阶段1步骤5)并推荐:如果已安装Docker则选Docker,否则如果有当前上下文则选Kubernetes,否则选直接安装。用一句话确认推荐;不要长篇大论。
kubectlPick how the user will sign in (question 4)
选择管理员登录方式(问题4)
This is question 4 in the call (or the
batched-five chat fallback). Two reasonable paths:
AskUserQuestion- GitHub. Drive GitHub's standard device-code flow over Coder's API. Print a short URL and an 8-character code; the user opens the URL on whatever device is handy (their phone is fine), pastes the code, approves access on GitHub, and Phase 4 captures the session and finishes setup. No browser on the install machine, no password to record.
- Email and password. Fully scripted, no GitHub round trip. Pick a strong password, create the admin account from the terminal, save the email and password to a file in the install's state directory.
Default to GitHub when the user can reach github.com on any
device. Fall back to email-and-password if they say no, ask
for a fully scripted setup, or you're running in headless mode
() where there's no human to type a code.
claude -pThe device-code path only works on deployments where the Coder
server has device flow enabled for its GitHub provider. Fresh
deployments do; custom-configured GitHub providers may not.
Phase 4 checks and the
endpoint before driving the flow,
and falls back to email-and-password if either says no.
default_provider_configured/users/oauth2/github/deviceFor the email-and-password path, prefill the email from git
config if present, instead of asking cold:
sh
EMAIL_DEFAULT="$(git config --global --get user.email 2>/dev/null || true)"Then confirm with the user. Don't make them type it from scratch
unless git doesn't have one.
这是调用(或批量五个问题的聊天回退)中的问题4。有两种合理路径:
AskUserQuestion- GitHub。通过Coder的API驱动GitHub标准设备码流。打印一个短URL和8位验证码;用户在任何可用设备(手机即可)上打开该URL,粘贴验证码,在GitHub上批准访问,阶段4将捕获会话并完成配置。无需在安装机器上打开浏览器,也无需记录密码。
- 邮箱和密码。完全脚本化,无需与GitHub交互。生成强密码,从终端创建管理员账户,并将邮箱和密码保存到安装状态目录中的文件中。
当用户可在任何设备上访问github.com时,默认选择GitHub。如果用户拒绝、要求完全脚本化安装,或运行在无界面模式()下(无人输入验证码),则回退到邮箱和密码方式。
claude -p设备码路径仅在Coder服务器为其GitHub提供商启用设备流的部署中有效。全新部署默认启用;自定义配置的GitHub提供商可能未启用。阶段4会在驱动流之前检查和端点,如果其中任何一个返回不可用,则回退到邮箱和密码方式。
default_provider_configured/users/oauth2/github/device对于邮箱和密码路径,如果git配置中存在邮箱,则预先填充该邮箱,而非直接询问:
sh
EMAIL_DEFAULT="$(git config --global --get user.email 2>/dev/null || true)"然后与用户确认。除非git中没有邮箱,否则不要让用户从头输入。
Pick the dev environment (question 5)
选择开发环境(问题5)
This is question 5 in the call (or the
batched-five chat fallback). Map the answer to a starter
template and an initial workspace decision:
AskUserQuestion| User says | Template | Build first workspace? |
|---|---|---|
| "yes", "sure", "go ahead" | match infra (below) | yes |
| "no", "skip", "I'll do it later" | still push starter | no |
| "Linux container in Docker", "docker", "a container" | | yes |
| "Kubernetes pod", "k8s", "on the cluster" | | yes |
| "cloud VM", "AWS", "GCP", "Azure" | matching cloud starter (see https://coder.com/docs/admin/templates.md) | yes |
| "my own", "I have a Terraform module", names a repo | none from skill; ask for the path; push that | yes if their template builds cleanly |
Default template by infrastructure when the user just says "yes":
| Infrastructure (question 3) | Default template |
|---|---|
| Docker | |
| Kubernetes / Helm | |
| Direct (binary + systemd) | |
If the user names a template you don't recognize, look it up
on (it's the
authoritative list) before assuming it doesn't exist. Don't
guess at template IDs; the canonical list is upstream and may
add entries between releases.
https://coder.com/docs/admin/templates.mdFor a user-supplied Terraform module, treat the path or repo
they gave you as the template source:
is not used; instead
directly. If the path is a git repo, ask whether to clone it or
use a local checkout.
coder templates initcoder templates push <name> -d <path>这是调用(或批量五个问题的聊天回退)中的问题5。将答案映射到入门模板和初始工作区决策:
AskUserQuestion| 用户表述 | 模板 | 是否构建首个工作区? |
|---|---|---|
| "yes"、"sure"、"go ahead" | 匹配基础设施(见下方) | 是 |
| "no"、"skip"、"I'll do it later" | 仍推送入门模板 | 否 |
| "Linux container in Docker"、"docker"、"a container" | | 是 |
| "Kubernetes pod"、"k8s"、"on the cluster" | | 是 |
| "cloud VM"、"AWS"、"GCP"、"Azure" | 匹配的云入门模板(见https://coder.com/docs/admin/templates.md) | 是 |
| "my own"、"I have a Terraform module"、提及仓库名称 | 技能不提供;询问路径;推送该模板 | 如果模板可正常构建则是 |
当用户仅回答"yes"时,根据基础设施选择默认模板:
| 基础设施(问题3) | 默认模板 |
|---|---|
| Docker | |
| Kubernetes / Helm | |
| 直接安装(二进制+systemd) | 如果已安装Docker则选 |
如果用户提及你不熟悉的模板,请先在(权威列表)中查找,再假设它不存在。不要猜测模板ID;规范列表在上游,可能会在版本间添加条目。
https://coder.com/docs/admin/templates.md对于用户提供的Terraform模块,将用户给出的路径或仓库作为模板源:不使用;而是直接使用。如果路径是git仓库,询问用户是克隆还是使用本地检出版本。
coder templates initcoder templates push <name> -d <path>Per-mode follow-ups (mode-specific extras)
模式特定跟进(模式专属额外操作)
Quick-start mode. Confirm defaults silently; don't ask.
- Web address. Default to Coder's automatic address. Tell the user, don't ask. Fall back to a local-only URL only if the auto-tunnel can't initialize (offline host) or the user asks. Phase 3 has the detection recipe.
*.try.coder.app
Production mode. Production needs more answers than
quick-start. Drive them through a single
call after the user answers question 2 with "For my team":
AskUserQuestionjson
{
"questions": [
{
"question": "What domain should people open in their browser to use Coder?",
"header": "Domain",
"multiSelect": false,
"options": [
{"label": "I have a subdomain in mind", "description": "e.g. coder.example.com. I'll ask which one next."},
{"label": "Use a Tailscale name (tailnet-only)", "description": "Reachable only inside your tailnet; no public DNS or cert."},
{"label": "Localhost / IP for now", "description": "Skip the domain; revisit once you have one."}
]
},
{
"question": "How do you want HTTPS handled?",
"header": "HTTPS",
"multiSelect": false,
"options": [
{"label": "Caddy in front", "description": "Recommended. Auto-renews Let's Encrypt certs."},
{"label": "Existing reverse proxy", "description": "nginx, traefik, cert-manager, etc.; I'll generate a config and you slot it in."},
{"label": "Coder terminates TLS itself", "description": "Single-binary install with cert files I'll point Coder at."},
{"label": "No TLS", "description": "Tailnet-only or other private network where TLS isn't required."}
]
},
{
"question": "Want a wildcard subdomain for in-workspace apps?",
"header": "Wildcard",
"multiSelect": false,
"options": [
{"label": "Yes, set it up", "description": "Workspace port-forwarded apps get their own *.coder.example.com URL."},
{"label": "No, skip it", "description": "You can add it later if you start using port-forwarded apps."}
]
},
{
"question": "Run Coder under systemd so it auto-starts on reboot?",
"header": "Service",
"multiSelect": false,
"options": [
{"label": "Yes", "description": "Recommended for any production deployment."},
{"label": "No, foreground for now", "description": "I'll just background it; you can wire systemd later."}
]
}
]
}Then the database question, separately so the user can paste a
connection string in plain text without a picker getting in
the way:
"Coder needs a Postgres in production. Do you have one I can point at, or want me to install Postgres on this host? If you have one, paste the connection string ()."postgres://user:pass@host:5432/db?sslmode=...
Follow-ups, also one chat at a time:
- If the user picked Caddy in front with a real domain,
ask which DNS provider hosts the zone (Cloudflare, Route 53,
etc.) so the wildcard cert can use DNS-01. The provider's
API token is a separate paste; confirm and never echo it back.
[set] - If the user picked a Tailscale name, mention up front
that you'll need Tailscale split-DNS configured for the
apex to resolve from non-tailnet contexts (workspace
containers in particular). See
if you hit it.
references/troubleshooting.md
For what kind of dev environments to push, reuse the question
5 mapping from the quick-start interview; production answers
the same question.
If quick-start state already exists on this host (a prior
run of this skill left and / or
), do not assume the user wants
it kept. Ask once with whether to remove the
quick-start tunnel server and its isolated config dir before
starting the production install:
~/.local/state/coder-install~/.config/coderv2-quickstartAskUserQuestionjson
{
"questions": [
{
"question": "I see a quick-start Coder running on this machine. Want me to take it down before I bring up production?",
"header": "Quick-start state",
"multiSelect": false,
"options": [
{"label": "Take it down and clean up", "description": "Stop the tunnel server, delete ~/.local/state/coder-install and ~/.config/coderv2-quickstart."},
{"label": "Take it down but keep the files", "description": "Stop the server; leave the state for me to inspect later."},
{"label": "Leave it running", "description": "Two Coder servers on one host; production still goes up under different config."}
]
}
]
}Whatever the user picks, never ; use the PID
file in (or the relevant systemd /
compose / helm command) so you don't kill an unrelated
process.
pkill coder$STATE_DIR/server.pidcoderFor configuration topics that don't all production deployments
need (wildcard DNS for in-workspace apps, custom GitHub / GitLab
OAuth, OIDC, external provisioners for cloud isolation), do not
ask in Phase 1. After the deployment is up and the user has
signed in, ask once at the end whether they want to wire any of
those in, and if so, point them at the matching page on
coder.com/docs:
- Wildcard URL: https://coder.com/docs/admin/networking/wildcard-access-url.md
- GitHub OAuth (default and custom): https://coder.com/docs/admin/users/github-auth.md
- OIDC (Okta, Entra, Google, etc.): https://coder.com/docs/admin/users/oidc-auth.md
- External authentication for workspaces (clone private repos): https://coder.com/docs/admin/external-auth.md
- External provisioners: https://coder.com/docs/admin/provisioners.md
Don't try to script those configurations from the skill. The env
vars and OAuth callback URLs change; the docs are kept current.
快速启动模式。静默确认默认值;不要询问。
- 网址。默认使用Coder自动生成的地址。告知用户,不要询问。仅当自动隧道无法初始化(离线主机)或用户要求时,才回退到本地URL。阶段3有检测方案。
*.try.coder.app
生产环境模式。生产环境比快速启动需要更多答案。当用户在问题2中回答"For my team"后,通过一次调用完成这些问题:
AskUserQuestionjson
{
"questions": [
{
"question": "What domain should people open in their browser to use Coder?",
"header": "Domain",
"multiSelect": false,
"options": [
{"label": "I have a subdomain in mind", "description": "e.g. coder.example.com. I'll ask which one next."},
{"label": "Use a Tailscale name (tailnet-only)", "description": "Reachable only inside your tailnet; no public DNS or cert."},
{"label": "Localhost / IP for now", "description": "Skip the domain; revisit once you have one."}
]
},
{
"question": "How do you want HTTPS handled?",
"header": "HTTPS",
"multiSelect": false,
"options": [
{"label": "Caddy in front", "description": "Recommended. Auto-renews Let's Encrypt certs."},
{"label": "Existing reverse proxy", "description": "nginx, traefik, cert-manager, etc.; I'll generate a config and you slot it in."},
{"label": "Coder terminates TLS itself", "description": "Single-binary install with cert files I'll point Coder at."},
{"label": "No TLS", "description": "Tailnet-only or other private network where TLS isn't required."}
]
},
{
"question": "Want a wildcard subdomain for in-workspace apps?",
"header": "Wildcard",
"multiSelect": false,
"options": [
{"label": "Yes, set it up", "description": "Workspace port-forwarded apps get their own *.coder.example.com URL."},
{"label": "No, skip it", "description": "You can add it later if you start using port-forwarded apps."}
]
},
{
"question": "Run Coder under systemd so it auto-starts on reboot?",
"header": "Service",
"multiSelect": false,
"options": [
{"label": "Yes", "description": "Recommended for any production deployment."},
{"label": "No, foreground for now", "description": "I'll just background it; you can wire systemd later."}
]
}
]
}然后单独询问数据库问题,以便用户可以纯文本粘贴连接字符串,不受选择器干扰:
"Coder生产环境需要Postgres数据库。你已有可用的数据库需要我指向,还是需要我在这台主机上安装Postgres?如果已有,请粘贴连接字符串()。"postgres://user:pass@host:5432/db?sslmode=...
后续跟进问题也需逐个聊天发送:
- 如果用户选择Caddy前置搭配真实域名,询问哪个DNS提供商托管该区域(Cloudflare、Route 53等),以便通配符证书可使用DNS-01验证。提供商的API令牌需单独粘贴;确认,绝不要回显。
[已设置] - 如果用户选择Tailscale名称,提前告知需要配置Tailscale split-DNS,以便apex域名可从非tailnet环境(尤其是工作区容器)解析。如果遇到问题,查看。
references/troubleshooting.md
对于要推送的开发环境类型,复用快速启动问答中的问题5映射;生产环境的答案相同。
如果这台主机上已存在快速启动状态(之前运行该技能留下了和/或),不要假设用户希望保留它。使用询问一次,是否在开始生产环境安装前移除快速启动隧道服务器及其隔离的配置目录:
~/.local/state/coder-install~/.config/coderv2-quickstartAskUserQuestionjson
{
"questions": [
{
"question": "I see a quick-start Coder running on this machine. Want me to take it down before I bring up production?",
"header": "Quick-start state",
"multiSelect": false,
"options": [
{"label": "Take it down and clean up", "description": "Stop the tunnel server, delete ~/.local/state/coder-install and ~/.config/coderv2-quickstart."},
{"label": "Take it down but keep the files", "description": "Stop the server; leave the state for me to inspect later."},
{"label": "Leave it running", "description": "Two Coder servers on one host; production still goes up under different config."}
]
}
]
}无论用户选择什么,绝不要使用;使用中的PID文件(或相关的systemd/compose/helm命令),以免杀死无关的进程。
pkill coder$STATE_DIR/server.pidcoder对于并非所有生产环境都需要的配置主题(工作区内应用的通配符DNS、自定义GitHub/GitLab OAuth、OIDC、用于云隔离的外部置备器),不要在阶段1询问。部署完成且用户登录后,在最后询问一次是否需要配置其中任何一项,如果需要,引导用户查看coder.com/docs上的对应页面:
- 通配符URL:https://coder.com/docs/admin/networking/wildcard-access-url.md
- GitHub OAuth(默认和自定义):https://coder.com/docs/admin/users/github-auth.md
- OIDC(Okta、Entra、Google等):https://coder.com/docs/admin/users/oidc-auth.md
- 工作区外部认证(克隆私有仓库):https://coder.com/docs/admin/external-auth.md
- 外部置备器:https://coder.com/docs/admin/provisioners.md
不要尝试从技能中脚本化这些配置。环境变量和OAuth回调URL会变化;文档会保持更新。
Probe the host (after the questions are answered)
探测主机(问题回答后)
With answers in hand, look at the machine to fill in remaining
defaults. This runs silently; don't make the user watch a
detection ceremony.
sh
uname -sm
command -v apt-get dnf yum apk brew zypper pacman 2>/dev/null
docker version --format '{{.Server.Version}}' 2>/dev/null
kubectl config current-context 2>/dev/null
helm version --short 2>/dev/null
coder --version 2>/dev/null
systemctl is-active coder 2>/dev/null
test -f "$HOME/.config/coderv2/url" && cat "$HOME/.config/coderv2/url"
env | grep -E '^(CODER_AGENT_TOKEN|CODER_WORKSPACE_NAME)=' || trueWhat to do with each result:
- succeeds. Plan to reuse the existing binary; skip the install in Phase 2 unless the user asked for a fresh install or production needs a newer release.
coder --version - No Docker, no Helm. If the user picked one of those, walk them through installing it first; otherwise the standalone install is the only option.
- exists and points somewhere the user wouldn't want clobbered. Plan to isolate
~/.config/coderv2/urlin Phase 4. Mention it in the plan paragraph; don't ask.CODER_CONFIG_DIR - No existing config dir. Use the default (). Do not isolate by default. Isolation is only for the conflict case.
~/.config/coderv2 - or
CODER_AGENT_TOKENis set. This is itself someone's Coder workspace. Phase 2 will refuse a host install and steer to Docker compose or a separate cluster context. Note this in the plan so the user knows why.CODER_WORKSPACE_NAME
Then show the user one plan paragraph (mode, infrastructure,
sign-in, any planned isolation, and any defaults you're applying)
and ask for a single yes/no before mutating anything.
Headless mode (, no interactive shell): the user
can't answer prompts and can't click a browser button. Treat the
original request as the approval. For sign-in, default to
email-and-password. If the prompt is missing something required
for production (web address, HTTPS strategy, database), refuse
with a one-line error listing what's missing in plain English,
instead of blocking on stdin.
claude -p获取答案后,查看机器情况以填充剩余默认值。此操作静默执行;不要让用户看到探测过程。
sh
uname -sm
command -v apt-get dnf yum apk brew zypper pacman 2>/dev/null
docker version --format '{{.Server.Version}}' 2>/dev/null
kubectl config current-context 2>/dev/null
helm version --short 2>/dev/null
coder --version 2>/dev/null
systemctl is-active coder 2>/dev/null
test -f "$HOME/.config/coderv2/url" && cat "$HOME/.config/coderv2/url"
env | grep -E '^(CODER_AGENT_TOKEN|CODER_WORKSPACE_NAME)=' || true如何处理每个结果:
- 执行成功。计划复用现有二进制文件;除非用户要求全新安装或生产环境需要更新版本,否则跳过阶段2的安装步骤。
coder --version - 无Docker,无Helm。如果用户选择了其中之一,先引导用户安装;否则独立安装是唯一选项。
- 存在且指向用户不希望被覆盖的位置。计划在阶段4隔离
~/.config/coderv2/url。在计划说明中提及;不要询问。CODER_CONFIG_DIR - 无现有配置目录。使用默认目录()。不要默认隔离。仅在冲突情况下才隔离。
~/.config/coderv2 - 或
CODER_AGENT_TOKEN已设置。当前环境本身是某个用户的Coder工作区。阶段2将拒绝主机安装,并引导至Docker compose或单独的集群上下文。在计划中注明,以便用户了解原因。CODER_WORKSPACE_NAME
然后向用户展示一段简短的计划说明(模式、基础设施、登录方式、任何计划的隔离操作、以及任何应用的默认值),并在修改任何内容前获取单一的是/否确认。
无界面模式(,无交互式shell):用户无法回答提示,也无法点击浏览器按钮。将原始请求视为批准。登录方式默认选择邮箱和密码。如果提示缺少生产环境所需的某些信息(网址、HTTPS策略、数据库),用一行通俗易懂的错误信息列出缺少的内容,拒绝执行,而非阻塞等待标准输入。
claude -pPhase 2: Install
阶段2:安装
Workspace-host guard. Before running any installer, check
whether you are inside someone's Coder workspace. If
or is set, the
workspace agent on this host is itself a binary; running
or letting overwrite
will disconnect the user. In that case:
CODER_AGENT_TOKENCODER_WORKSPACE_NAMEcoderpkill coderinstall.sh/usr/local/bin/coder- Refuse a host install unless the user explicitly asked for nested Coder.
- Docker compose is fine when scoped to a sub-directory and a non-default port. Workspaces ship Docker; the inner server runs in its own container.
- Kubernetes via Helm is fine when targeted at a separate cluster context, not the workspace's host.
See
if this guard fires.
references/troubleshooting.md#never-pkill-coder-on-a-coder-workspaceOtherwise, install. Always prefer the canonical install script:
it detects the package manager, falls back to a standalone
tarball, and supports an unprivileged user-local install.
Standalone Linux/macOS, system-wide:
sh
curl -fsSL https://coder.com/install.sh | shStandalone Linux/macOS, no sudo:
sh
curl -fsSL https://coder.com/install.sh \
| sh -s -- --method standalone --prefix "$HOME/.local"
export PATH="$HOME/.local/bin:$PATH"For Docker compose, Helm, or anything else, follow the matching
docs page rather than scripting it from the skill:
- Docker: https://coder.com/docs/install/docker.md
- Kubernetes / Helm: https://coder.com/docs/install/kubernetes.md
- Standalone CLI: https://coder.com/docs/install/cli.md
- Rancher / OpenShift / Cloud / Air-gapped: see the install/ index page.
Useful flags ( for the full set):
install.sh--help- (default) or
--mainline: pick the release channel. Use--stablefor production unless the user asked for mainline.--stable - : pin a specific version.
--version X.Y.Z - : install Terraform alongside Coder. Use this when the deployment will run Terraform locally (almost every template does).
--with-terraform - : user-local install with no package manager and no sudo.
--method standalone --prefix DIR - : print the commands without running them.
--dry-run
Verify with . Exit criterion: the binary runs.
coder --version工作区主机防护。在运行任何安装程序前,检查是否处于某个用户的Coder工作区中。如果或已设置,则该主机上的工作区代理本身就是二进制文件;运行或让覆盖会断开用户连接。在这种情况下:
CODER_AGENT_TOKENCODER_WORKSPACE_NAMEcoderpkill coderinstall.sh/usr/local/bin/coder- 拒绝主机安装,除非用户明确要求嵌套Coder。
- Docker compose是可行的,只要限定在子目录和非默认端口中。工作区已预装Docker;内部服务器在自己的容器中运行。
- 通过Helm部署Kubernetes是可行的,只要目标是单独的集群上下文,而非工作区的主机。
如果该防护触发,查看。
references/troubleshooting.md#never-pkill-coder-on-a-coder-workspace否则,执行安装。始终优先使用规范的安装脚本:它会检测包管理器,回退到独立tarball,并支持非特权用户本地安装。
Linux/macOS独立安装,系统级:
sh
curl -fsSL https://coder.com/install.sh | shLinux/macOS独立安装,无需sudo:
sh
curl -fsSL https://coder.com/install.sh \
| sh -s -- --method standalone --prefix "$HOME/.local"
export PATH="$HOME/.local/bin:$PATH"对于Docker compose、Helm或其他方式,请遵循对应文档页面,而非从技能中脚本化:
- Docker:https://coder.com/docs/install/docker.md
- Kubernetes / Helm:https://coder.com/docs/install/kubernetes.md
- 独立CLI:https://coder.com/docs/install/cli.md
- Rancher / OpenShift / 云 / 离线环境:查看install/索引页面。
install.sh--help- (默认)或
--mainline:选择发布渠道。生产环境使用--stable,除非用户要求mainline。--stable - :固定特定版本。
--version X.Y.Z - :随Coder一起安装Terraform。当部署将在本地运行Terraform时(几乎所有模板都需要)使用此参数。
--with-terraform - :用户本地安装,无需包管理器和sudo。
--method standalone --prefix DIR - :打印命令但不执行。
--dry-run
使用验证。退出标准:二进制文件可运行。
coder --versionPhase 3: Start the server
阶段3:启动服务器
Skill outputs that need to survive the chat live in one directory
the skill creates up front and prints back to the user in Phase 7.
Do not scatter dotfiles across . The directory follows
XDG: if set, otherwise
.
$HOME$XDG_STATE_HOME/coder-install$HOME/.local/state/coder-installsh
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/coder-install"
mkdir -p "$STATE_DIR"需要在聊天中保留的技能输出存储在技能预先创建的一个目录中,并在阶段7中打印给用户。不要在中分散点文件。该目录遵循XDG规范:如果设置了则为,否则为。
$HOME$XDG_STATE_HOME$XDG_STATE_HOME/coder-install$HOME/.local/state/coder-installsh
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/coder-install"
mkdir -p "$STATE_DIR"Quick-start path
快速启动路径
Default: let open its built-in tunnel. The tunnel
is the most-reliable single-machine path because it routes
around host-firewall and docker-bridge issues that bite
local-only binds. Don't pass ; the server picks a
URL and prints it to stderr.
coder server--access-url*.try.coder.appUnder the hood, reads (or generates and persists)
a wireguard keypair in the user's config dir at
, opens a
wireguard connection to , and serves
traffic that arrives there. The hostname is derived from the
keypair, so it's stable across restarts as long as the keypair
file is intact.
coder server${XDG_CONFIG_HOME:-$HOME/.config}/coderv2/devtunnelpit-1.try.coder.appThe skill does not derive the URL itself. The server prints
a banner that includes:
text
View the Web UI:
https://<id>.pit-1.try.coder.appParse the URL from the line right after . The
tunnel handshake usually completes in 2-5 seconds.
View the Web UI:For standalone host install:
sh
nohup coder server > "$STATE_DIR/server.log" 2>&1 &
echo $! > "$STATE_DIR/server.pid"For Docker compose: don't run directly; bring
up the compose stack and let the container hold the log. Skip
the state-dir log/pid (the container is its own supervisor;
logs come from ). The auto-tunnel still
works inside the container as long as the compose file persists
the wireguard keypair (the upstream does).
coder serverdocker compose logscompose.yamlWait for readiness:
sh
coder_log() {
if [ -f "$STATE_DIR/server.log" ]; then
cat "$STATE_DIR/server.log"
elif [ -f docker-compose.yml ] || [ -f compose.yaml ]; then
docker compose logs coder 2>&1
else
return 1
fi
}
ACCESS_URL=""
for _ in $(seq 1 60); do
ACCESS_URL="$(coder_log 2>/dev/null \
| awk '/View the Web UI:/{getline; print; exit}' \
| grep -oE 'https?://[a-zA-Z0-9.-]+(\:[0-9]+)?')"
if [ -n "$ACCESS_URL" ] && \
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1; then
break
fi
if coder_log 2>/dev/null | grep -q 'create tunnel'; then
ACCESS_URL=""
break
fi
sleep 1
doneLocal-only fallback (no internet egress, or user explicitly
asked for local-only). Only fall back if the loop above exits
with :
ACCESS_URL=""sh
kill "$(cat "$STATE_DIR/server.pid")" 2>/dev/null || true
ACCESS_URL="http://localhost:7080"
nohup coder server \
--access-url "$ACCESS_URL" \
--http-address 0.0.0.0:7080 \
> "$STATE_DIR/server.log" 2>&1 &
echo $! > "$STATE_DIR/server.pid"
for _ in $(seq 1 60); do
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1 && break
sleep 1
doneBind to , not . The Docker
workspace agent reaches the server via ,
so a host-loopback bind is unreachable from inside the workspace
container. On NixOS the firewall may still drop the SYN; see
.
0.0.0.0:7080127.0.0.1:7080host.docker.internalreferences/troubleshooting.md#nixos-firewall-blocks-docker-bridge默认:让打开其内置隧道。隧道是最可靠的单机器路径,因为它可以绕过主机防火墙和docker-bridge问题,这些问题会影响仅本地绑定的情况。不要传递;服务器会选择一个 URL并打印到标准错误输出。
coder server--access-url*.try.coder.app在底层,会读取(或生成并持久化)用户配置目录中的wireguard密钥对,打开与的wireguard连接,并处理到达该地址的流量。主机名由密钥对派生,因此只要密钥对文件 intact,重启后地址保持稳定。
coder server${XDG_CONFIG_HOME:-$HOME/.config}/coderv2/devtunnelpit-1.try.coder.app本技能不会自行推导URL。服务器会打印包含以下内容的横幅:
text
View the Web UI:
https://<id>.pit-1.try.coder.app从之后的行中解析URL。隧道握手通常在2-5秒内完成。
View the Web UI:独立主机安装:
sh
nohup coder server > "$STATE_DIR/server.log" 2>&1 &
echo $! > "$STATE_DIR/server.pid"Docker compose:不要直接运行;启动compose栈,让容器保存日志。跳过状态目录中的日志/PID(容器本身就是管理器;日志来自)。只要compose文件持久化wireguard密钥对(上游已实现),自动隧道在容器内仍可正常工作。
coder serverdocker compose logscompose.yaml等待就绪:
sh
coder_log() {
if [ -f "$STATE_DIR/server.log" ]; then
cat "$STATE_DIR/server.log"
elif [ -f docker-compose.yml ] || [ -f compose.yaml ]; then
docker compose logs coder 2>&1
else
return 1
fi
}
ACCESS_URL=""
for _ in $(seq 1 60); do
ACCESS_URL="$(coder_log 2>/dev/null \
| awk '/View the Web UI:/{getline; print; exit}' \
| grep -oE 'https?://[a-zA-Z0-9.-]+(\:[0-9]+)?')"
if [ -n "$ACCESS_URL" ] && \
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1; then
break
fi
if coder_log 2>/dev/null | grep -q 'create tunnel'; then
ACCESS_URL=""
break
fi
sleep 1
done仅本地回退(无互联网出口,或用户明确要求仅本地)。仅当上述循环退出时才回退:
ACCESS_URL=""sh
kill "$(cat "$STATE_DIR/server.pid")" 2>/dev/null || true
ACCESS_URL="http://localhost:7080"
nohup coder server \
--access-url "$ACCESS_URL" \
--http-address 0.0.0.0:7080 \
> "$STATE_DIR/server.log" 2>&1 &
echo $! > "$STATE_DIR/server.pid"
for _ in $(seq 1 60); do
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1 && break
sleep 1
done绑定到,而非。Docker工作区代理通过访问服务器,因此主机环回绑定无法从工作区容器内访问。在NixOS上,防火墙可能仍会丢弃SYN包;查看。
0.0.0.0:7080127.0.0.1:7080host.docker.internalreferences/troubleshooting.md#nixos-firewall-blocks-docker-bridgeProduction path
生产环境路径
Production deployments are configured via env, on the deployment
manifest (Helm values, compose , systemd
environment file). The minimal env (access URL, Postgres URL,
TLS, optional wildcard) and the canonical Helm values file are
in the upstream docs. Don't reproduce them here; follow:
environment:- https://coder.com/docs/install/kubernetes.md for Helm.
- https://coder.com/docs/install/docker.md for compose.
- https://coder.com/docs/admin/setup.md for the env-var
matrix (,
CODER_ACCESS_URL,CODER_PG_CONNECTION_URL,CODER_TLS_*,CODER_REDIRECT_TO_ACCESS_URL).CODER_WILDCARD_ACCESS_URL
Roll out the deployment, then wait for against the
public URL:
/healthzsh
for _ in $(seq 1 120); do
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1 && break
sleep 1
doneVerify the wildcard if you set one:
sh
curl -fsS "https://app-test.${WILDCARD_DOMAIN}/healthz"生产环境部署通过环境变量、部署清单(Helm配置、compose、systemd环境文件)进行配置。最小环境变量(访问URL、Postgres URL、TLS、可选通配符)和规范Helm配置文件在上游文档中。不要在此处重复;请遵循:
environment:- https://coder.com/docs/install/kubernetes.md(Helm)。
- https://coder.com/docs/install/docker.md(compose)。
- https://coder.com/docs/admin/setup.md(环境变量矩阵:、
CODER_ACCESS_URL、CODER_PG_CONNECTION_URL、CODER_TLS_*、CODER_REDIRECT_TO_ACCESS_URL)。CODER_WILDCARD_ACCESS_URL
部署完成后,等待公共URL的端点就绪:
/healthzsh
for _ in $(seq 1 120); do
curl -fsS "$ACCESS_URL/healthz" >/dev/null 2>&1 && break
sleep 1
done如果设置了通配符,验证其可用性:
sh
curl -fsS "https://app-test.${WILDCARD_DOMAIN}/healthz"Phase 4: Sign in as the admin
阶段4:以管理员身份登录
Whoever signs in first becomes the admin (Owner) automatically.
Existing-login guard. Before running any command that
writes a session, check whether the host already has one. Only
isolate if the existing
points at a real deployment the user wouldn't want overwritten
(e.g. , an internal team URL). The default
is not to isolate; most users have no prior config and
should write to the standard .
coderCODER_CONFIG_DIR~/.config/coderv2/urlhttps://dev.coder.comcoder login~/.config/coderv2sh
default_dir="${XDG_CONFIG_HOME:-$HOME/.config}/coderv2"
if [ -f "$default_dir/url" ]; then
existing="$(cat "$default_dir/url")"
case "$existing" in
"$ACCESS_URL"|"") : ;; # No conflict.
*)
# Existing login points elsewhere; isolate.
export CODER_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/coderv2-quickstart"
export CODER_CACHE_DIRECTORY="${XDG_CACHE_HOME:-$HOME/.cache}/coderv2-quickstart"
mkdir -p "$CODER_CONFIG_DIR" "$CODER_CACHE_DIRECTORY"
;;
esac
fiWithout isolation, would overwrite the existing
URL and session and kick the user out of their real deployment.
coder login首个登录的用户将自动成为管理员(Owner)。
现有登录防护。在运行任何会写入会话的命令前,检查主机是否已有会话。仅当现有指向用户不希望被覆盖的真实部署(例如、内部团队URL)时,才隔离。默认不隔离;大多数用户没有先前的配置,应写入标准的。
coder~/.config/coderv2/urlhttps://dev.coder.comCODER_CONFIG_DIRcoder login~/.config/coderv2sh
default_dir="${XDG_CONFIG_HOME:-$HOME/.config}/coderv2"
if [ -f "$default_dir/url" ]; then
existing="$(cat "$default_dir/url")"
case "$existing" in
"$ACCESS_URL"|"") : ;; # 无冲突。
*)
# 现有登录指向其他位置;隔离。
export CODER_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/coderv2-quickstart"
export CODER_CACHE_DIRECTORY="${XDG_CACHE_HOME:-$HOME/.cache}/coderv2-quickstart"
mkdir -p "$CODER_CONFIG_DIR" "$CODER_CACHE_DIRECTORY"
;;
esac
fi如果不隔离,会覆盖现有URL和会话,并将用户从其真实部署中踢出。
coder loginGitHub path (device code, no browser on this machine)
GitHub路径(设备码,无需在本机打开浏览器)
Drive the GitHub sign-in over GitHub's standard device flow,
proxied through Coder's API. The user gets a short URL and a
one-time code, types it on whatever device is handy, and the
install completes without opening a browser on the install
machine.
First, confirm the deployment can do device flow:
sh
DEVICE_OK=true
curl -fsS "$ACCESS_URL/api/v2/users/authmethods" \
| python3 -c '
import json, sys
d = json.load(sys.stdin)
sys.exit(0 if d["github"].get("default_provider_configured") else 1)
' || DEVICE_OK=false
curl -fsS "$ACCESS_URL/api/v2/users/oauth2/github/device" >/dev/null 2>&1 || DEVICE_OK=falseIf (custom GitHub provider, or device flow
disabled), fall back to the email-and-password path. Don't reach
for the browser flow unless the user has a working browser on
this machine and asked for it.
DEVICE_OK=falseWhen device flow is available, drive it with the two scripts
bundled in this skill:
and
.
Run them as three separate tool calls, with a chat message
to the user between them. The full protocol, with rationale and
failure modes, is in
.
scripts/github-device-fetch.shscripts/github-device-poll.shreferences/first-user-github-device.md-
Fetch. One short shell command:sh
ACCESS_URL="$ACCESS_URL" \ bash "$SKILL_DIR/scripts/github-device-fetch.sh"Returns in ~3 seconds. Writesand prints$STATE_DIR/github-device.{jar,env}/USER_CODE/VERIFY_URIon stdout. Do NOT include the polling loop in this call; if you do, the command sits for up to 15 minutes and the user never sees the code.EXPIRES_IN -
Tell the user, in chat (not in a shell command). Readand
$VERIFY_URIfrom$USER_CODE(or from the fetch script's stdout) and send the user a chat message like:$STATE_DIR/github-device.envTo sign in to Coder, open this on any device (your phone is fine):$VERIFY_URIEnter this code:$USER_CODESay "ok" when you're done and I'll finish setting you up as the admin.Wait for the user's acknowledgement ("ok", "done", "entered it"). If they ask for a different sign-in method instead, abandon the device flow and switch to email-and-password. -
Poll. A separate shell command:sh
ACCESS_URL="$ACCESS_URL" \ bash "$SKILL_DIR/scripts/github-device-poll.sh"Loops until the user finishes on github.com, writes the session token into, removes the cookie jar / env / response scratch files (success or failure), and verifies with$CODER_CONFIG_DIR/{url,session}andcoder whoami.coder users list
$SKILL_DIRSKILL.md~/.claude/plugins/coder/skills/setup--plugin-dirThe reason for the split is that most agent tool runners buffer
a shell command's stdout and only return it when the command
exits. A combined fetch-and-poll script prints the code at the
start but the runner doesn't surface it until the polling exits,
which means the user sits looking at a hung chat for the full
15-minute device-code window. The recipe document opens with
this warning; respect it.
users listOWNER通过Coder的API驱动GitHub登录,采用GitHub标准设备流。用户会获得一个短URL和一次性验证码,在任何可用设备上输入,无需在安装机器上打开浏览器即可完成安装。
首先,确认部署支持设备流:
sh
DEVICE_OK=true
curl -fsS "$ACCESS_URL/api/v2/users/authmethods" \
| python3 -c '
import json, sys
d = json.load(sys.stdin)
sys.exit(0 if d["github"].get("default_provider_configured") else 1)
' || DEVICE_OK=false
curl -fsS "$ACCESS_URL/api/v2/users/oauth2/github/device" >/dev/null 2>&1 || DEVICE_OK=false如果(自定义GitHub提供商,或设备流已禁用),回退到邮箱和密码路径。除非用户在本机有可用浏览器并要求,否则不要使用浏览器流。
DEVICE_OK=false当设备流可用时,使用本技能中捆绑的两个脚本驱动:和。将它们作为三个单独的工具调用运行,在调用之间向用户发送聊天消息。完整协议、原理和故障模式记录在中。
scripts/github-device-fetch.shscripts/github-device-poll.shreferences/first-user-github-device.md-
获取。一个简短的shell命令:sh
ACCESS_URL="$ACCESS_URL" \ bash "$SKILL_DIR/scripts/github-device-fetch.sh"约3秒后返回。写入并在标准输出打印$STATE_DIR/github-device.{jar,env}/USER_CODE/VERIFY_URI。不要在此调用中包含轮询循环;否则命令会等待长达15分钟,用户永远看不到验证码。EXPIRES_IN -
告知用户,通过聊天(而非shell命令)。从(或获取脚本的标准输出)中读取
$STATE_DIR/github-device.env和$VERIFY_URI,并向用户发送如下聊天消息:$USER_CODE要登录Coder,请在任何设备上打开此链接(手机即可):$VERIFY_URI输入此验证码:$USER_CODE完成后请回复"ok",我会将你设置为管理员。等待用户确认("ok"、"done"、"已输入")。如果用户要求改用其他登录方式,则放弃设备流并切换到邮箱和密码方式。 -
轮询。一个单独的shell命令:sh
ACCESS_URL="$ACCESS_URL" \ bash "$SKILL_DIR/scripts/github-device-poll.sh"循环直到用户在github.com上完成操作,将会话令牌写入,删除cookie jar/环境/响应临时文件(无论成功或失败),并通过$CODER_CONFIG_DIR/{url,session}和coder whoami验证。coder users list
$SKILL_DIRSKILL.md~/.claude/plugins/coder/skills/setup--plugin-dir拆分调用的原因是大多数Agent工具运行器会缓冲shell命令的标准输出,仅在命令退出时返回。如果将获取和轮询合并为一个脚本,虽然会在开始时打印验证码,但运行器会在轮询退出后才显示,这意味着用户会看到聊天停滞,直到15分钟的设备码窗口结束。文档开头已警告此问题;请遵守。
users listOWNEREmail and password path (no browser)
邮箱和密码路径(无需浏览器)
Use with flags, including
. Without that flag (or
in the env), the CLI prompts on
stdin and the headless flow hangs.
coder login--first-user-*--first-user-trial=falseCODER_FIRST_USER_TRIAL=falsePass the password through the env, not the command line:
sh
export CODER_FIRST_USER_PASSWORD="$PASSWORD"
coder login "$ACCESS_URL" \
--first-user-email "$EMAIL" \
--first-user-username "$USERNAME" \
--first-user-full-name "$FULL_NAME" \
--first-user-trial=false
unset CODER_FIRST_USER_PASSWORDThe password has no recovery path. Persist it to a mode-0600
file in :
$STATE_DIRsh
umask 0077
printf 'url=%s\nusername=%s\nemail=%s\npassword=%s\n' \
"$ACCESS_URL" "$USERNAME" "$EMAIL" "$PASSWORD" \
> "$STATE_DIR/credentials"
chmod 0600 "$STATE_DIR/credentials"Verify with and .
coder whoamicoder users listAnything more advanced about the upstream flags
(persistent tokens, JSON output, the form) is in
https://coder.com/docs/reference/cli/login.md.
coder login--token使用并搭配参数,包括。如果缺少该参数(或环境中未设置),CLI会在标准输入提示,导致无界面流挂起。
coder login--first-user-*--first-user-trial=falseCODER_FIRST_USER_TRIAL=false通过环境变量传递密码,而非命令行:
sh
export CODER_FIRST_USER_PASSWORD="$PASSWORD"
coder login "$ACCESS_URL" \
--first-user-email "$EMAIL" \
--first-user-username "$USERNAME" \
--first-user-full-name "$FULL_NAME" \
--first-user-trial=false
unset CODER_FIRST_USER_PASSWORD密码无法恢复。将其持久化到中权限为0600的文件:
$STATE_DIRsh
umask 0077
printf 'url=%s\nusername=%s\nemail=%s\npassword=%s\n' \
"$ACCESS_URL" "$USERNAME" "$EMAIL" "$PASSWORD" \
> "$STATE_DIR/credentials"
chmod 0600 "$STATE_DIR/credentials"通过和验证。
coder whoamicoder users listPhase 5: Push a starter template
阶段5:推送入门模板
Pick the template that matches the chosen infrastructure. The
starter list and required parameters live in
https://coder.com/docs/admin/templates.md (and the
per-template pages under it). Don't hard-code the list here; it
changes.
sh
TEMPLATE_DIR="$(mktemp -d)/$TEMPLATE_NAME"
coder templates init --id "$TEMPLATE_ID" "$TEMPLATE_DIR"
coder templates push "$TEMPLATE_NAME" -d "$TEMPLATE_DIR" --yes
coder templates listFor non-secret template variables, use :
--variables-filesh
cat > "$(mktemp).yaml" <<EOF
namespace: coder
use_kubeconfig: false
EOF
coder templates push "$TEMPLATE_NAME" --variables-file <that-file> --yesNever echo secret values back to the user, never put them in
, and never pass them as (they
leak into every template version and the audit log). For cloud
templates that need provider credentials, see
https://coder.com/docs/admin/templates.md for the secret
variable pattern, and https://coder.com/docs/admin/provisioners.md
if you need to keep credentials off the server.
terraform.tfvars--variable选择与所选基础设施匹配的模板。入门模板列表和所需参数记录在https://coder.com/docs/admin/templates.md(及其中的每个模板页面)中。不要在此处硬编码列表;它会变化。
sh
TEMPLATE_DIR="$(mktemp -d)/$TEMPLATE_NAME"
coder templates init --id "$TEMPLATE_ID" "$TEMPLATE_DIR"
coder templates push "$TEMPLATE_NAME" -d "$TEMPLATE_DIR" --yes
coder templates list对于非机密模板变量,使用:
--variables-filesh
cat > "$(mktemp).yaml" <<EOF
namespace: coder
use_kubeconfig: false
EOF
coder templates push "$TEMPLATE_NAME" --variables-file <that-file> --yes绝不要向用户回显机密值,不要将其放入,也不要通过传递(它们会泄露到每个模板版本和审计日志中)。对于需要提供商凭据的云模板,请查看https://coder.com/docs/admin/templates.md了解机密变量模式,如果需要将凭据保存在服务器外,请查看https://coder.com/docs/admin/provisioners.md。
terraform.tfvars--variablePhase 6: Create a workspace (optional)
阶段6:创建工作区(可选)
If the user said no in question 5, skip this phase entirely.
Don't pile on a follow-up ask; respect the answer.
Discover required parameters before . Skipping
this costs a wasted retry and several seconds of perceived
latency: without all required parameters either
blocks on stdin (interactive) or fails with
. Pull the template
first:
coder createcoder createRequired parameter ... was not providedsh
TEMPLATE_PULL="$(mktemp -d)/$TEMPLATE_NAME"
coder templates pull "$TEMPLATE_NAME" "$TEMPLATE_PULL"Then scan for
blocks. Each one looks like:
$TEMPLATE_PULL/main.tfdata "coder_parameter"hcl
data "coder_parameter" "jetbrains_ides" {
display_name = "..."
type = "list(string)"
default = jsonencode([])
...
}For every parameter without a , you need a value. For
list / map / object parameters, the value must be JSON; an
empty list is , an empty map . The starter Docker
template's is the canonical example: it's a
required multi-select with no default and a sensible "none"
value is .
default[]{}jetbrains_ides[]When the user just said "yes, build the first one", pick
sensible defaults for every required parameter (empty list for
multi-selects with no default, the first option for
single-select enums) without asking. Only ask the user when a
parameter is required, has no default, and has no obvious
zero-value (a free-text string used as an identifier, for
example).
Then create the workspace in one shot:
sh
coder create "$WORKSPACE_NAME" \
--template "$TEMPLATE_NAME" \
--parameter 'jetbrains_ides=[]' \
--yesPass parameters with repeated . List,
map, and object parameters need a JSON value. Never call
without all required parameters and hope; the
failure mode is a wasted retry the user has to wait through.
--parameter "name=value"coder createFor , the namespace must already exist.
kubernetesWait for the agent to be ready, not just for the build to
succeed. A successful build with
only means the workspace's infrastructure stood up; the agent
must finish its startup script before and work.
latest_build.status=runningcoder sshcoder opensh
WS_DEADLINE=$(( $(date +%s) + 300 ))
while :; do
STATE=$(coder list -o json 2>/dev/null | python3 -c '
import json, sys
d = json.load(sys.stdin)
for w in d:
if w["name"] != "'"$WORKSPACE_NAME"'": continue
for r in (w["latest_build"].get("resources") or []):
for a in (r.get("agents") or []):
print(a["lifecycle_state"]); raise SystemExit
print("no-agent")
')
case "$STATE" in
ready) break ;;
start_error|start_timeout) echo "agent failed: $STATE" >&2; exit 1 ;;
esac
[ "$(date +%s)" -gt "$WS_DEADLINE" ] && { echo "agent did not reach ready in 5min (last=$STATE)" >&2; exit 1; }
sleep 5
doneIf the agent stalls in , see
.
connectingreferences/troubleshooting.md#workspace-agent-cant-reach-the-server如果用户在问题5中回答否,则完全跳过此阶段。不要追加跟进问题;尊重用户的答案。
在前发现所需参数。跳过此步骤会导致重试失败,并增加感知延迟:如果缺少所有必需参数,会阻塞等待标准输入(交互式)或失败并提示。先拉取模板:
coder createcoder createRequired parameter ... was not providedsh
TEMPLATE_PULL="$(mktemp -d)/$TEMPLATE_NAME"
coder templates pull "$TEMPLATE_NAME" "$TEMPLATE_PULL"然后扫描中的块。每个块类似:
$TEMPLATE_PULL/main.tfdata "coder_parameter"hcl
data "coder_parameter" "jetbrains_ides" {
display_name = "..."
type = "list(string)"
default = jsonencode([])
...
}每个没有的参数都需要值。对于列表/映射/对象参数,值必须是JSON;空列表为,空映射为。入门Docker模板的是典型示例:它是必填的多选参数,无默认值,合理的"无"值为。
default[]{}jetbrains_ides[]当用户仅回答"yes, build the first one"时,为每个必需参数选择合理的默认值(无默认值的多选参数为空列表,单选枚举选第一个选项),无需询问。仅当参数必填、无默认值且无明显零值(例如用作标识符的自由文本字符串)时,才询问用户。
然后一次性创建工作区:
sh
coder create "$WORKSPACE_NAME" \
--template "$TEMPLATE_NAME" \
--parameter 'jetbrains_ides=[]' \
--yes通过重复传递参数。列表、映射和对象参数需要JSON值。绝不要在缺少所有必需参数的情况下调用;失败模式会导致用户等待不必要的重试。
--parameter "name=value"coder create对于,命名空间必须已存在。
kubernetes等待代理就绪,而非仅等待构建成功。构建成功且仅意味着工作区的基础设施已启动;代理必须完成启动脚本后,和才能正常工作。
latest_build.status=runningcoder sshcoder opensh
WS_DEADLINE=$(( $(date +%s) + 300 ))
while :; do
STATE=$(coder list -o json 2>/dev/null | python3 -c '
import json, sys
d = json.load(sys.stdin)
for w in d:
if w["name"] != "'"$WORKSPACE_NAME"'": continue
for r in (w["latest_build"].get("resources") or []):
for a in (r.get("agents") or []):
print(a["lifecycle_state"]); raise SystemExit
print("no-agent")
')
case "$STATE" in
ready) break ;;
start_error|start_timeout) echo "agent failed: $STATE" >&2; exit 1 ;;
esac
[ "$(date +%s)" -gt "$WS_DEADLINE" ] && { echo "agent did not reach ready in 5min (last=$STATE)" >&2; exit 1; }
sleep 5
done如果代理停滞在状态,查看。
connectingreferences/troubleshooting.md#workspace-agent-cant-reach-the-serverPhase 7: Hand off
阶段7:交接
Print one short, plain-English block at the end. This is what
the user reads first; write it like a handoff, not a config
dump. Substitute the actual values; don't print fields that
don't apply.
Before you write the message, decide which Logs and Stop
command pair matches the actual install: host install with
/ , Docker compose, systemd, or
Kubernetes / Helm. Pick ONE pair. The angle-bracket
notation in the templates below is a hint to
you, not text to copy. Resolve it to the one matching command
before you show anything to the user.
server.logserver.pid<one of: ...>Do not refer to yourself or to "the skill" in any user-facing
text. Speak in the first person about what was installed ("I
installed Coder", "setup wrote ..."); never say "this skill"
or "the setup skill".
GitHub device-code path (already signed in by now). Example
shown for a host install; pick one Logs / Stop pair that
matches your install:
text
=== Coder is ready ===
You're signed in as the admin.
Coder is running here as a host process. The binary is at
$(command -v coder); its data lives in
${CODER_CONFIG_DIR:-$HOME/.config/coderv2}.
Open Coder in your browser:
$ACCESS_URL
To start, stop, or check on Coder later:
- Logs: tail -f $STATE_DIR/server.log
- Stop: kill $(cat $STATE_DIR/server.pid)
What to try next:
- Open "$WORKSPACE_NAME" in Coder right now.
- Use it like any other dev environment from your editor or
a browser; no extra setup on your end.
Ask me about anything else; I'm still here.
Working files are in $STATE_DIR. Delete that directory to undo
what setup wrote here.For Docker compose, swap the "Coder is running" sentence and
the Logs / Stop lines for:
text
Coder is running in Docker on this machine. The compose file
is at $STATE_DIR/docker-compose.yml.
- Logs: docker compose -f $STATE_DIR/docker-compose.yml logs -f coder
- Stop: docker compose -f $STATE_DIR/docker-compose.yml downFor systemd:
text
Coder is running as a systemd service named `coder`.
- Logs: journalctl -u coder -f
- Stop: sudo systemctl stop coderFor Kubernetes / Helm:
text
Coder is running in Kubernetes as the `coder` Helm release in
the `coder` namespace.
- Logs: kubectl logs -n coder deploy/coder -f
- Stop: helm uninstall coder -n coderPrint exactly one "Coder is running" sentence, one Logs line,
and one Stop line. Never paste the alternatives at the user.
For the email-and-password path, replace the "You're signed in"
line with the credentials block:
text
Sign in at $ACCESS_URL with:
Email: $EMAIL
Password: $PASSWORD
Setup wrote them to $STATE_DIR/credentials (mode 0600). Don't
share that file.For the browser-button GitHub fallback (rare; only used when
device-flow isn't available), replace the "You're signed in"
line with:
text
Open $ACCESS_URL in your browser and click "Sign in with GitHub".
You'll be the admin once you finish.If the user mentioned (or might benefit from) Premium features
like Workspace Proxies, groups, audit log retention, or template
ACLs, mention they can request a license later. Don't drive
that flow yourself; it collects PII (name, phone, job title,
company, country, dev count) and posts to the licensor:
text
If you ever want to try Premium features (Workspace Proxies,
groups, audit log retention, template ACLs), let me know and
I'll point you at https://coder.com/trial to request a key.
The trial signup collects some company info, so I'll leave
that part to you.Mention Coder Agents at the end of the handoff. Coder
Agents is the built-in chat that runs AI coding agents inside
the deployment, against a configured LLM provider. A fresh
user usually doesn't know it's there. One short line is
enough; don't pitch it.
text
One more thing: Coder has a built-in agents UI that runs AI
coding agents inside your deployment against your own LLM key.
Want me to wire it up?If the user says yes, follow
. It
documents the full six-step recipe: pick provider, take key
(via env var, never pasted in chat), look up the live API
surface from , create the provider, create
the flagship model and mark it default, grant the Coder Agents
User role, verify with .
Don't read that file unless the user actually wants Agents
wired up; the rest of this skill never needs it.
references/coder-agents.md/swagger/doc.jsonGET /api/experimental/chats/modelsClosing offer. End the handoff with one short,
plain-English line. Don't list topic URLs at the user; the
agent (you) does the work, the user just says yes:
"Anything else? OIDC sign-in, GitLab, a custom domain, a different kind of dev environment, or that Coder Agents setup? Just tell me which."
Do not include documentation links, raw file paths to
upstream docs, or URLs in any of the
user-facing text above. Those exist for the agent's benefit;
the user installed Coder so the agent would do this work for
them. Mentioning a doc page tells them "go read the manual,"
which defeats the purpose of having installed the skill.
.mdcoder.com/docs/...最后打印一段简短的通俗易懂的内容。这是用户首先会阅读的部分;请像交接一样撰写,而非配置转储。替换为实际值;不要打印不适用的字段。
撰写消息前,确定哪个日志和停止命令对与实际安装匹配:主机安装搭配/、Docker compose、systemd或Kubernetes/Helm。选择一对。以下模板中的符号是给你的提示,而非要复制的文本。在展示给用户前,将其解析为与Coder实际运行方式匹配的单一命令。
server.logserver.pid<one of: ...>在任何面向用户的文本中,不要提及自己或"技能"。用第一人称描述已安装的内容("我安装了Coder"、"配置过程写入了...");绝不要说"这个技能"或"安装技能"。
GitHub设备码路径(此时用户已登录)。以下示例针对主机安装;选择与你的安装匹配的日志/停止命令对:
text
=== Coder已就绪 ===
你已以管理员身份登录。
Coder作为主机进程运行在此处。二进制文件位于$(command -v coder);数据存储在${CODER_CONFIG_DIR:-$HOME/.config/coderv2}。
在浏览器中打开Coder:
$ACCESS_URL
后续启动、停止或检查Coder状态:
- 查看日志: tail -f $STATE_DIR/server.log
- 停止服务: kill $(cat $STATE_DIR/server.pid)
下一步可尝试:
- 立即在Coder中打开"$WORKSPACE_NAME"。
- 像使用其他开发环境一样,从编辑器或浏览器中使用它;无需额外配置。
如有其他需求,请告诉我;我会继续协助。
工作文件存储在$STATE_DIR。删除该目录可撤销本次配置写入的内容。对于Docker compose,将"Coder正在运行"句子和日志/停止行替换为:
text
Coder在这台机器的Docker中运行。compose文件位于$STATE_DIR/docker-compose.yml。
- 查看日志: docker compose -f $STATE_DIR/docker-compose.yml logs -f coder
- 停止服务: docker compose -f $STATE_DIR/docker-compose.yml down对于systemd:
text
Coder作为名为`coder`的systemd服务运行。
- 查看日志: journalctl -u coder -f
- 停止服务: sudo systemctl stop coder对于Kubernetes / Helm:
text
Coder在Kubernetes中运行,作为`coder`命名空间中的`coder`Helm发布。
- 查看日志: kubectl logs -n coder deploy/coder -f
- 停止服务: helm uninstall coder -n coder仅打印一句"Coder正在运行"、一行日志命令和一行停止命令。绝不要向用户粘贴替代选项。
对于邮箱和密码路径,将"你已登录"行替换为凭据块:
text
在$ACCESS_URL登录,凭据如下:
邮箱: $EMAIL
密码: $PASSWORD
配置过程已将凭据写入$STATE_DIR/credentials(权限0600)。请勿共享该文件。对于浏览器按钮GitHub回退(罕见;仅在设备流不可用时使用),将"你已登录"行替换为:
text
在浏览器中打开$ACCESS_URL并点击"Sign in with GitHub"。完成后你将成为管理员。如果用户提及(或可能受益于)高级功能,如Workspace Proxies、群组、审计日志保留或模板ACL,可提及他们稍后可申请许可证。不要自行驱动该流程;它会收集个人身份信息(姓名、电话、职位、公司、国家、开发人员数量)并发送给许可证提供商:
text
如果你想尝试高级功能(Workspace Proxies、群组、审计日志保留、模板ACL),请告诉我,我会引导你访问https://coder.com/trial申请密钥。试用注册会收集一些公司信息,因此我会将这部分操作交给你完成。在交接末尾提及Coder Agents。Coder Agents是内置聊天功能,可在部署内运行AI编码Agent,对接已配置的LLM提供商。新用户通常不知道它的存在。一句话即可;不要过度推销。
text
还有一件事:Coder内置了Agents UI,可在你的部署内运行AI编码Agent,对接你自己的LLM密钥。需要我帮你配置吗?如果用户同意,请遵循。该文档记录了完整的六步流程:选择提供商、获取密钥(通过环境变量,绝不要在聊天中粘贴)、从查看实时API接口、创建提供商、创建旗舰模型并设置为默认、授予Coder Agents用户角色、通过验证。仅当用户确实需要配置Agents时才读取该文件;本技能的其他部分无需使用。
references/coder-agents.md/swagger/doc.jsonGET /api/experimental/chats/models最终提议。用一句简短的通俗易懂的话结束交接。不要向用户列出主题URL;Agent(你)会完成工作,用户只需回答是:
"还有其他需求吗?OIDC登录、GitLab、自定义域名、其他类型的开发环境,或Coder Agents配置?只需告诉我即可。"
不要在上述面向用户的文本中包含文档链接、上游文档的原始文件路径或URL。这些是供Agent使用的;用户安装Coder是为了让Agent代劳这些工作。提及文档页面相当于告诉用户"去读手册",违背了安装该技能的初衷。
.mdcoder.com/docs/...Anti-patterns
反模式
- Do not write to the user like a sysadmin. If a user-facing
message contains a flag (), an env var (
--first-user-trial), or an internal noun ("OAuth provider", "ingress", "terraform"), rewrite it. Decide what they need to know in plain English, pick a default, and ask for one short answer.CODER_ACCESS_URL - Do not duplicate Coder's docs. If a question is about a topic that lives on coder.com/docs (OIDC, custom OAuth, templates, provisioners, wildcard URL, TLS, upgrades, etc.), point at the docs page and apply what it says. Do not transcribe it into the skill; it will go stale.
- Do not run (or any blanket
pkill coderagainst the coder binary) whenkillis set. That terminates the workspace agent the user is connected through. SeeCODER_AGENT_TOKEN.references/troubleshooting.md#never-pkill-coder-on-a-coder-workspace - Do not run destructive cleanup commands without an explicit
user request. ,
docker compose down -v, andhelm uninstall coderpermanently destroy the database and every workspace built from it.kubectl delete namespace coder - Do not pipe to
install.shunless the user asked for a system-wide install. Default to user-local where possible.sudo sh - Do not isolate by default. Only isolate when the host already has a Coder login pointing somewhere the user wouldn't want overwritten.
CODER_CONFIG_DIR - Do not assume Docker. Ask the infrastructure question. Don't silently default; even when Docker is installed, the user may want Kubernetes or a direct install.
- Do not ask the Phase 1 questions as plain chat text when
is available. The structured picker is the supported UX; chat-message fallbacks lose the click-to- answer affordance, options look like prose the user has to parse, and the agent is more likely to drop questions. Use the two
AskUserQuestioncalls described in Phase 1 (four questions, then one). Only fall back to chat text if the runner reports the tool as unavailable.AskUserQuestion - Do not collapse Phase 1 into a two-question interview.
The five core questions (familiarity, mode, infrastructure,
sign-in, dev environment) are non-negotiable. Real users
have reported agents asking only mode + sign-in and silently
guessing the rest, ending up with a Docker install and a
workspace they didn't know they were building. Use
and ship all five questions across the two documented calls.
AskUserQuestion - Do not call before reading the template's required parameters. A blind
coder createagainst a starter that has required list parameters (e.g.coder createon the Docker template) hangs on stdin or fails outright, then forces a retry.jetbrains_idescoder templates pull- a quick scan of is cheaper than the wasted retry.
main.tf
- a quick scan of
- Do not echo cloud credentials, OAuth client secrets,
provisioner keys, or the admin password back to the user.
Confirm receipt with or a redacted form.
[set] - Do not ask the user to paste an LLM API key into chat.
Chat transcripts and shell history persist; a key dropped
inline is leaked the moment the user says "send this log to
support." Have them export it in their shell first (or
read -s LLM_KEY) and then readexport LLM_KEY=...from your environment without ever printing it. If a user pastes anyway, accept the value, finish the setup, and tell them in the handoff to rotate the key on the provider's dashboard.$LLM_KEY - Do not opt the user into the upstream enterprise-trial
license flow unless they explicitly asked. Always pass
to
--first-user-trial=falseand never setcoder login. The signup-time path collects PII (name, phone, job title, company, country, dev count) and POSTs it to Coder's licensor; there is no consent UX in the skill for that. If a user later wants Premium features,CODER_FIRST_USER_TRIAL=trueandPOST /api/v2/licensesaccept a JWT they request themselves.coder licenses add - Do not skip the readiness probe. A successful
/healthzexit doesn't mean the API is up.coder server - Do not run in a foreground that ties up the chat. Background it and tail the log.
coder server - Do not run the GitHub device-flow scripts back to back in
one tool call. Tool runners buffer shell stdout until the
command exits. A fetch immediately followed by a poll prints
the early, then sits in a 15-minute polling loop, so the code stays in the buffer until the loop times out and the user never sees it. Run
user_code, send the user a chat message with the URL and code fromscripts/github-device-fetch.sh, wait for them to acknowledge, then run$STATE_DIR/github-device.envas a separate tool call. Seescripts/github-device-poll.sh.references/first-user-github-device.md - Do not inline the device-flow shell into the chat. The
scripts under are the source of truth. Don't paste their contents back into Phase 4 or copy fragments of them inline; call them by path. Inlining drifts from the bundled version on every change and skips the trap-based cleanup.
scripts/ - Do not narrate "the skill" at the user. They asked you to install Coder; they didn't subscribe to the implementation. Never say "this skill", "the setup skill", "I ran the skill", or "the skill saved ...". Use first person about what was installed ("I installed Coder", "setup wrote credentials to ...") in every user-facing message and in the final handoff.
- Do not paste the placeholders at the user. The angle-bracket alternatives in the Phase 7 templates are notes to you. Pick the single command pair that matches how Coder is actually running (host / Docker compose / systemd / Kubernetes) before printing.
<one of: ...> - Do not put (or any other docs URL) in user-facing text. Documentation pages are for the agent to read and apply, not for the user to study. If a topic is worth raising, offer to handle it ("want me to wire up Okta sign-in?") and read the docs page yourself when they say yes. Real users have reported the Phase 7 handoff dumping five
coder.com/docs/*.mdURLs at them, which made the install feel like homework..md - Do not hand the user a CLI walkthrough as "what to try
next." ,
coder templates init,coder templates push,coder ssh: those are agent operations, not user instructions. If the user wants one of those, offer it in plain English and run it for them. The point of the skill is that the user doesn't have to learn the CLI.coder licenses add - Do not leave OAuth scratch files lying around. The GitHub
device-flow recipe writes a cookie jar and an env file under
. Both step 1 and step 3 must install
$STATE_DIR/github-device.*cleanups; step 3 must always remove them on exit, success or failure. They contain OAuth state and have no value once the session token is captured.trap - Do not disable telemetry on the user's behalf. It defaults
to on, and Coder strips PII before sending. The user can opt
out themselves with ; don't ask them and don't decide for them.
CODER_TELEMETRY_ENABLE=false
- 不要以系统管理员的口吻与用户沟通。如果面向用户的消息包含参数()、环境变量(
--first-user-trial)或内部名词("OAuth provider"、"ingress"、"terraform"),请重写。用通俗易懂的语言确定用户需要了解的内容,选择默认值,并提出一个简短的问题。CODER_ACCESS_URL - 不要重复Coder的文档。如果问题涉及coder.com/docs上的主题(OIDC、自定义OAuth、模板、置备器、通配符URL、TLS、升级等),请指向文档页面并应用其中的内容。不要将其转录到技能中;否则会过时。
- 当已设置时,不要运行
CODER_AGENT_TOKEN(或任何针对coder二进制文件的全面pkill coder命令)。这会终止用户连接的工作区代理。查看kill。references/troubleshooting.md#never-pkill-coder-on-a-coder-workspace - 不要在未获得用户明确请求的情况下运行破坏性清理命令。、
docker compose down -v和helm uninstall coder会永久销毁数据库和所有基于该模板构建的工作区。kubectl delete namespace coder - 不要将通过管道传递给
install.sh,除非用户要求系统级安装。尽可能默认选择用户本地安装。sudo sh - 不要默认隔离。仅当主机已存在指向用户不希望被覆盖的Coder登录时才隔离。
CODER_CONFIG_DIR - 不要假设用户使用Docker。询问基础设施问题。不要默认选择;即使已安装Docker,用户也可能希望使用Kubernetes或直接安装。
- 当可用时,不要将阶段1的问题作为纯聊天文本提出。结构化选择器是支持的用户体验;聊天消息回退会失去点击回答的便利性,选项看起来像用户需要解析的散文,且Agent更可能遗漏问题。使用阶段1中描述的两次
AskUserQuestion调用(四个问题,然后一个问题)。仅当运行环境报告该工具不可用时,才回退到聊天文本。AskUserQuestion - 不要将阶段1简化为两个问题的问答。五个核心问题(熟悉度、模式、基础设施、登录方式、开发环境)是必不可少的。实际用户反馈,Agent仅询问模式+登录方式并默默猜测其余内容,最终导致Docker安装和用户不知道的工作区被构建。使用并通过两次已记录的调用完成所有五个问题。
AskUserQuestion - 不要在读取模板的必需参数前调用。盲目调用
coder create针对具有必需列表参数的入门模板(例如Docker模板的coder create)会阻塞等待标准输入或直接失败,然后需要重试。jetbrains_ides+快速扫描coder templates pull比重试更高效。main.tf - 不要向用户回显云凭据、OAuth客户端密钥、置备器密钥或管理员密码。用或脱敏形式确认已收到。
[已设置] - 不要让用户在聊天中粘贴LLM API密钥。聊天记录和shell历史会持久化;密钥直接粘贴会在用户说"发送此日志给支持"时泄露。让用户先在shell中导出(或
read -s LLM_KEY),然后从环境中读取export LLM_KEY=...,绝不打印。如果用户仍粘贴,接受该值,完成配置,并在交接中告知用户在提供商控制台轮换密钥。$LLM_KEY - 不要在未获得用户明确请求的情况下,让用户加入上游企业试用许可证流程。始终向传递
coder login,绝不设置--first-user-trial=false。注册流程会收集个人身份信息(姓名、电话、职位、公司、国家、开发人员数量)并POST到Coder的许可证提供商;本技能中没有针对此的同意用户体验。如果用户稍后需要高级功能,CODER_FIRST_USER_TRIAL=true和POST /api/v2/licenses接受用户自行申请的JWT。coder licenses add - 不要跳过就绪探测。
/healthz成功退出并不意味着API已启动。coder server - 不要在前台运行,以免占用聊天。将其后台运行并跟踪日志。
coder server - 不要在一个工具调用中连续运行GitHub设备流脚本。工具运行器会缓冲shell标准输出,直到命令退出。如果获取后立即轮询,虽然会提前打印,但会进入15分钟的轮询循环,导致验证码一直留在缓冲区,直到循环超时,用户永远看不到。运行
user_code,向用户发送包含scripts/github-device-fetch.sh中URL和验证码的聊天消息,等待用户确认,然后单独运行$STATE_DIR/github-device.env。查看scripts/github-device-poll.sh。references/first-user-github-device.md - 不要将设备流shell命令内联到聊天中。下的脚本是权威来源。不要将其内容粘贴回阶段4或复制片段内联;通过路径调用。内联会在每次更改时偏离捆绑版本,并跳过基于陷阱的清理。
scripts/ - 不要向用户叙述"技能"。用户要求的是安装Coder;并非关注实现细节。绝不要说"这个技能"、"安装技能"、"我运行了该技能"或"该技能保存了..."。在所有面向用户的消息和最终交接中,用第一人称描述已安装的内容("我安装了Coder"、"配置过程将凭据写入了...")。
- 不要向用户粘贴占位符。阶段7模板中的尖括号替代选项是给你的提示。选择与Coder实际运行方式匹配的单一命令对(主机/Docker compose/systemd/Kubernetes)后再打印。
<one of: ...> - 不要在面向用户的文本中放入(或任何其他文档URL)。文档页面是供Agent阅读和应用的,而非用户学习的。如果某个主题值得提及,主动提出处理("需要我配置Okta登录吗?"),并在用户同意后自行阅读文档页面。实际用户反馈,阶段7交接中列出五个
coder.com/docs/*.mdURL会让安装感觉像家庭作业。.md - 不要将CLI操作指南作为"下一步尝试"交给用户。、
coder templates init、coder templates push、coder ssh:这些是Agent操作,而非用户指令。如果用户需要其中某项,用通俗易懂的语言提出并为其执行。该技能的核心价值在于用户无需学习CLI。coder licenses add - 不要留下OAuth临时文件。GitHub设备流方案会在下写入cookie jar和环境文件。步骤1和步骤3必须安装
$STATE_DIR/github-device.*清理;步骤3必须在退出时始终删除它们,无论成功或失败。它们包含OAuth状态,会话令牌捕获后无任何价值。trap - 不要代表用户禁用遥测。遥测默认开启,Coder会在发送前剥离个人身份信息。用户可自行通过选择退出;不要询问或替用户决定。
CODER_TELEMETRY_ENABLE=false
References
参考文件
This skill keeps three reference files and two scripts.
Everything else (OIDC, custom OAuth, GitLab, wildcard URL, TLS
termination, external provisioners, template authoring, install
layouts, upgrades) is on coder.com/docs and should be read from
there.
Each reference file is loaded on demand. Read a file only when
its trigger condition fires; never read all three eagerly.
- : the GitHub device-code flow protocol used in Phase 4 (when to use it, the three-tool-call structure, common failures). Bespoke, not in upstream docs. Trigger: Phase 4 picks the GitHub device-code path.
references/first-user-github-device.md - : the six-step recipe for wiring Coder Agents (LLM provider + flagship model + role + verification) at the end of Phase 7. Trigger: the user accepts the Phase 7 Coder Agents offer. Skip entirely if the user declines.
references/coder-agents.md - : skill-specific gotchas not in the upstream docs. Covers the workspace-host guard, NixOS firewall on the docker bridge, the
references/troubleshooting.mdloopback issue, embedded Postgres failing on ARM, the bundled Terraform installer's PGP key, fresh Docker group not picked up by the running server, Caddy redirect loops in front of Coder, and home-router DNS rebind protection on tailnet apex names. Trigger: something stalls and the failure mode isn't already covered at the call site.host.docker.internal - : step 1 of the device flow. Primes the OAuth cookies, fetches the device code, writes
scripts/github-device-fetch.sh.$STATE_DIR/github-device.{jar,env} - : step 3 of the device flow. Polls the callback, writes the session, cleans up scratch files.
scripts/github-device-poll.sh
For everything else, navigate https://coder.com/docs/llms.txt.
本技能包含三个参考文件和两个脚本。其他所有内容(OIDC、自定义OAuth、GitLab、通配符URL、TLS终止、外部置备器、模板编写、安装布局、升级)均在coder.com/docs上,应从那里读取。
每个参考文件按需加载。仅当触发条件满足时才读取文件;不要主动读取所有三个文件。
- :阶段4中使用的GitHub设备码流协议(使用场景、三工具调用结构、常见故障)。为定制内容,未在上游文档中记录。触发条件:阶段4选择GitHub设备码路径。
references/first-user-github-device.md - :在阶段7末尾配置Coder Agents的六步流程(LLM提供商+旗舰模型+角色+验证)。触发条件:用户接受阶段7的Coder Agents提议。如果用户拒绝,则完全跳过。
references/coder-agents.md - :技能特定的陷阱,未在上游文档中记录。涵盖工作区主机防护、docker bridge上的NixOS防火墙、
references/troubleshooting.md环回问题、ARM架构上嵌入式Postgres失败、捆绑Terraform安装程序的PGP密钥、运行中的服务器未识别新的Docker组、Coder前置的Caddy重定向循环、家庭路由器对tailnet apex名称的DNS rebind保护。触发条件:出现停滞且故障模式未在调用点覆盖。host.docker.internal - :设备流的步骤1。初始化OAuth cookie,获取设备码,写入
scripts/github-device-fetch.sh。$STATE_DIR/github-device.{jar,env} - :设备流的步骤3。轮询回调,写入会话,清理临时文件。
scripts/github-device-poll.sh
其他所有内容,请浏览https://coder.com/docs/llms.txt。