windows-local-dev-services

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Windows Local Dev Services

Windows本地开发服务

Overview

概述

Start the local service, prove it is reachable, and report the exact working launch path. Prefer fast diagnosis over repeating the same broken startup command.
This skill is most useful for Codex and Claude Code on Windows. Use it before attempting to start, restart, or verify a Windows localhost service so known Windows and sandbox launch failures are handled up front. It can also guide ChatGPT or Claude when shell access is unavailable by returning commands for the user to run manually.
启动本地服务,验证其可访问性,并报告确切的可用启动路径。优先快速诊断问题,而非重复执行相同的失败启动命令。
此技能在Windows系统上的Codex和Claude Code中最为实用。在尝试启动、重启或验证Windows本地主机服务前使用它,可预先处理已知的Windows和沙箱启动故障。当无法访问Shell时,它还可以通过返回供用户手动运行的命令,指导ChatGPT或Claude完成操作。

Platform Support

平台支持

  • ChatGPT: use when tool/shell access exists, or provide manual PowerShell steps.
  • Codex: primary use case; run commands in the repo and verify localhost.
  • Claude: use when Claude Skills and shell/tool access are available.
  • Claude Code: copy the skill folder into
    ~/.claude/skills/
    for personal use or
    .claude/skills/
    for project use.
If the platform cannot run shell commands, do not claim the service was started. Provide the exact commands and checks for the user to run.
  • ChatGPT:当具备工具/Shell访问权限时使用,或提供手动PowerShell步骤。
  • Codex:主要使用场景;在代码仓库中运行命令并验证本地主机服务。
  • Claude:当Claude Skills和Shell/工具访问权限可用时使用。
  • Claude Code:将技能文件夹复制到
    ~/.claude/skills/
    供个人使用,或复制到
    .claude/skills/
    供项目使用。
如果平台无法运行Shell命令,请勿声称服务已启动。请提供供用户运行的确切命令和检查步骤。

Core Rule

核心规则

A localhost workflow is not done until both are true:
  1. The launch command is known and repeatable.
  2. The app responds on the expected localhost URL or health endpoint.
本地主机工作流需同时满足以下两个条件才算完成:
  1. 启动命令已知且可重复执行。
  2. 应用能在预期的本地主机URL或健康端点上响应请求。

Long-Running Localhost Server Rule

长期运行本地主机服务器规则

Do not run persistent server commands such as
npm run dev
,
npm run start
,
npm run platform:start
,
uvicorn
,
flask run
,
python -m http.server
,
pnpm dev
,
yarn dev
, or
bun run dev
in the foreground unless the user explicitly asks for an interactive foreground terminal.
Default behavior for persistent localhost servers:
  1. Launch a detached/background process.
  2. Redirect stdout/stderr to temporary or repo-approved local logs.
  3. Run bounded readiness checks against an HTTP health URL, known app URL, or TCP port.
  4. Return a concise status summary.
  5. Never wait indefinitely.
If an agent must run a command that may be long-running, use one of:
  • a timeout wrapper.
  • a detached/background launch.
  • an explicit user-approved foreground run.
If a command produces no readiness signal within the bounded wait, stop and summarize. Do not "just wait".
For commands that are expected to run longer than 30 minutes, or that have already exceeded 30 minutes, use 30-minute checkpoints. At each checkpoint, inspect whether the process is making progress before deciding what to do next:
  • Still running and progressing: report the observed signal, such as log growth, CPU activity, test count movement, build output, health status, or file changes, then continue to the next 30-minute checkpoint.
  • Ready: stop waiting and proceed to the next task step.
  • Stalled: capture a safe log tail and process/port status, then stop the current-run process if it is clearly owned by this agent run, or ask before stopping anything ambiguous.
  • Waiting for input, credentials, network, or a locked resource: stop waiting, report the blocker, and ask for the missing input or approval instead of silently burning time.
  • Orphaned after interruption: follow the interrupted-command cleanup rule before rerunning anything.
除非用户明确要求交互式前台终端,否则请勿在前台运行持久化服务器命令,例如
npm run dev
、
npm run start
、
npm run platform:start
、
uvicorn
、
flask run
、
python -m http.server
、
pnpm dev
、
yarn dev
或
bun run dev
。
持久化本地主机服务器的默认行为:
  1. 以分离式/后台进程启动。
  2. 将stdout/stderr重定向到临时或仓库认可的本地日志文件。
  3. 针对HTTP健康URL、已知应用URL或TCP端口执行有限就绪检查。
  4. 返回简洁的状态摘要。
  5. 绝不无限期等待。
如果Agent必须运行可能长期执行的命令,请使用以下方式之一:
  • 超时包装器。
  • 分离式/后台启动。
  • 用户明确批准的前台运行。
如果命令在有限等待时间内未发出就绪信号,请停止执行并总结情况。请勿“只是等待”。
对于预计运行时间超过30分钟,或已运行超过30分钟的命令,请使用30分钟检查点。在每个检查点,先检查进程是否在推进,再决定下一步操作:
  • 仍在运行且持续推进:报告观察到的信号,例如日志增长、CPU活动、测试计数变化、构建输出、健康状态或文件变更,然后继续到下一个30分钟检查点。
  • 已就绪:停止等待,进入下一个任务步骤。
  • 已停滞:捕获安全的日志尾部内容和进程/端口状态,然后停止当前运行的进程(如果明确属于本次Agent运行),或在停止任何不明确的进程前先询问用户。
  • 等待输入、凭据、网络或锁定资源:停止等待,报告阻塞因素,并请求缺失的输入或批准,而非静默消耗时间。
  • 中断后成为孤儿进程:在重新运行任何命令前,遵循中断命令清理规则。

Workflow

工作流

1. Discover the app root and native startup command

1. 发现应用根目录和原生启动命令

Inspect these files before running random commands:
  • package.json
    scripts.
  • README setup/start instructions.
  • helper script files such as
    start-local-dev.ps1
    ,
    dev.ps1
    ,
    dev.*
    , or
    start.*
    .
  • .env
    ,
    .env.local
    ,
    .env.example
    , and documented environment requirements.
Identify:
  • expected host and port.
  • package manager: npm, pnpm, yarn, bun, dotnet, python, etc.
  • auth/dev mode.
  • required
    .env
    source.
Reuse an existing
.env
when present. If the project expects one and it is missing, create it from
.env.example
only when safe and obvious.
在运行随机命令前,先检查以下文件:
  • package.json
    中的脚本。
  • README中的设置/启动说明。
  • 辅助脚本文件,例如
    start-local-dev.ps1
    、
    dev.ps1
    、
    dev.*
    或
    start.*
    。
  • .env
    、
    .env.local
    、
    .env.example
    以及文档记录的环境要求。
确定:
  • 预期的主机和端口。
  • 包管理器:npm、pnpm、yarn、bun、dotnet、python等。
  • 认证/开发模式。
  • 必需的
    .env
    源文件。
如果存在现有
.env
文件,请复用。如果项目需要
.env
但文件缺失,仅在安全且明确的情况下从
.env.example
创建。

2. Check whether the target port is already in use

2. 检查目标端口是否已被占用

Adjust the port number to match the project.
powershell
$port = 3000
$conn = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
if ($conn) { Get-Process -Id $conn.OwningProcess | Select-Object Id,ProcessName,Path }
Before launching, check whether the intended port is already listening. If the port is already listening, health-check it first.
  • If health is OK, do not start another server.
  • If a stale/broken process owns the port or a launcher is stale, ask before killing unless it is clearly created by the current run and safe to stop.
  • Use process IDs in local notes.
  • Do not over-log private command lines if they contain secrets.
  • Reuse, stop, or change port only after understanding whether the process is the same app.
调整端口号以匹配项目需求。
powershell
$port = 3000
$conn = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
if ($conn) { Get-Process -Id $conn.OwningProcess | Select-Object Id,ProcessName,Path }
启动前,检查目标端口是否已在监听。如果端口已在监听,先进行健康检查。
  • 如果健康状态正常,请勿启动另一个服务器。
  • 如果端口被陈旧/故障进程占用,或启动器已失效,除非明确属于本次运行且安全停止,否则请先询问用户再终止进程。
  • 在本地记录中使用进程ID。
  • 如果命令行包含机密信息,请勿过度记录。
  • 仅在了解进程是否为同一应用后,再选择复用、停止或更改端口。

3. Resolve runtimes and package-manager commands dynamically

3. 动态解析运行时和包管理器命令

Do not hardcode a user-specific path as the default. Find the runtime or package manager first:
powershell
Get-Command pnpm.cmd -ErrorAction SilentlyContinue
Get-Command npm.cmd -ErrorAction SilentlyContinue
Get-Command yarn.cmd -ErrorAction SilentlyContinue
Get-Command bun.exe -ErrorAction SilentlyContinue
Get-Command python.exe -ErrorAction SilentlyContinue
Get-Command py.exe -ErrorAction SilentlyContinue
For Python apps, check
python.exe
, then
py.exe
, then any platform-provided or bundled Python runtime exposed by the current agent environment. Use the platform/bundled runtime only as a discovered fallback, not as a hardcoded default. Explain which runtime was selected.
If a wrapper script fails, or PATH discovery does not find the expected command, call the resolved executable directly:
powershell
$pnpm = (Get-Command pnpm.cmd -ErrorAction Stop).Source
& $pnpm dev
Use hardcoded paths only as a last-resort local fallback, and explain why.
请勿将用户特定路径硬编码为默认值。先查找运行时或包管理器:
powershell
Get-Command pnpm.cmd -ErrorAction SilentlyContinue
Get-Command npm.cmd -ErrorAction SilentlyContinue
Get-Command yarn.cmd -ErrorAction SilentlyContinue
Get-Command bun.exe -ErrorAction SilentlyContinue
Get-Command python.exe -ErrorAction SilentlyContinue
Get-Command py.exe -ErrorAction SilentlyContinue
对于Python应用,先检查
python.exe
,再检查
py.exe
,然后检查当前Agent环境提供的任何平台自带或捆绑的Python运行时。仅将平台/捆绑运行时作为发现的回退选项,而非硬编码默认值。请说明选择了哪个运行时。
如果包装脚本失败,或PATH未找到预期命令,请直接调用解析后的可执行文件:
powershell
$pnpm = (Get-Command pnpm.cmd -ErrorAction Stop).Source
& $pnpm dev
仅在万不得已时使用硬编码路径作为本地回退选项,并说明原因。

4. Diagnose unknown failures with bounded commands

4. 使用有限命令诊断未知故障

When the launch failure mode is unknown, run a short bounded diagnostic command so the real error is visible. Do not leave a persistent server command in the foreground without a timeout or explicit user-approved foreground run.
Examples:
powershell
npm run dev
pnpm dev
yarn dev
bun run dev
If a PowerShell helper script is the documented startup path, run it once with a timeout wrapper or equivalent bounded shell execution to see whether it fails before binding the port. If it fails due to wrapper/tooling issues, stop retrying it and run the underlying command directly.
当启动故障模式未知时,运行一个简短的有限诊断命令,以便查看真实错误。请勿在没有超时或用户明确批准的情况下,在前台运行持久化服务器命令。
示例:
powershell
npm run dev
pnpm dev
yarn dev
bun run dev
如果PowerShell辅助脚本是文档记录的启动路径,请使用超时包装器或等效的有限Shell执行运行一次,查看它在绑定端口前是否失败。如果因包装器/工具问题失败,请停止重试,直接运行底层命令。

5. Start long-running servers detached

5. 以分离式启动长期运行的服务器

Use this when the service is long-running and the working command is known. A reliable launch pattern is:
  1. Check the port.
  2. Normalize duplicate process environment keys before
    Start-Process
    .
  3. Start the server with stdout/stderr logs.
  4. Poll a documented health endpoint such as
    /api/health
    , or the root URL when no health endpoint exists.
  5. After the launch shell command returns, re-check the port or HTTP endpoint before claiming the server persists.
  6. If a Codex sandbox launch does not persist after the shell command returns, retry with an escalated/unsandboxed launch when the environment supports it, then repeat the post-return port or HTTP check.
  7. Keep restart and verification as separate steps: stop or reuse an old server, start the new server, then health-check with a short timeout. Do not bundle stop/start/health into one long command where one hung step hides the actual state.
  8. Report the exact URL, command, process id, and log paths.
Readiness checks must be bounded:
  • Use a clear max wait, usually 60-120 seconds unless the user explicitly asks otherwise.
  • Poll every 1-3 seconds.
  • Success must be based on observable readiness: HTTP 200/expected status, TCP port listening, or a known health endpoint.
  • Never rely only on
    Start-Process
    exit state as proof the app is running.
  • If not ready by timeout, stop and report the command attempted, safe log tail, port status, process status, and next manual action. Do not keep waiting.
当服务长期运行且工作命令已知时使用此方法。可靠的启动模式如下:
  1. 检查端口。
  2. 在
    Start-Process
    前规范化重复的进程环境变量键。
  3. 启动服务器并记录stdout/stderr日志。
  4. 轮询文档记录的健康端点,例如
    /api/health
    ;如果没有健康端点,则轮询根URL。
  5. 启动Shell命令返回后,重新检查端口或HTTP端点,再声称服务器持续运行。
  6. 如果Codex沙箱启动在Shell命令返回后无法持续运行,当环境支持时,使用升级/非沙箱启动重试,然后重复返回后的端口或HTTP检查。
  7. 将重启和验证作为单独步骤:停止或复用旧服务器,启动新服务器,然后通过短超时进行健康检查。请勿将停止/启动/健康检查捆绑到一个长命令中,以免某个挂起步骤隐藏实际状态。
  8. 报告确切的URL、命令、进程ID和日志路径。
就绪检查必须是有限的:
  • 使用明确的最大等待时间,通常为60-120秒,除非用户明确要求其他时长。
  • 每1-3秒轮询一次。
  • 成功必须基于可观察的就绪状态:HTTP 200/预期状态、TCP端口监听或已知健康端点响应。
  • 绝不能仅依赖
    Start-Process
    的退出状态来证明应用正在运行。
  • 如果超时后仍未就绪,请停止执行,报告尝试的命令、安全的日志尾部内容、端口状态、进程状态以及下一步手动操作。请勿继续等待。

6. Preferred Windows-safe launcher example

6. 推荐的Windows安全启动器示例

Prefer a temporary
.ps1
launcher script when the startup logic contains quotes,
#
,
=
,
$
, JSON,
.IndexOf("=")
,
.StartsWith("#")
, environment parsing, or multiline script logic. Avoid deeply nested one-line PowerShell strings inside
Start-Process -ArgumentList
for those cases.
Good patterns:
  • Write a temporary
    .ps1
    launcher script and call it with
    Start-Process powershell.exe -ArgumentList @("-NoExit", "-ExecutionPolicy", "Bypass", "-File", "<launcher.ps1>")
    when an interactive visible window is explicitly wanted.
  • For automated agent launches, use
    Start-Process powershell.exe -ArgumentList @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $launcher)
    with
    -WindowStyle Hidden
    and redirected logs.
  • Use
    Start-Job
    for short background setup only, not persistent server ownership unless logs/process lifecycle are clear.
  • Use a simple
    cmd /c
    or PowerShell command only when no nested quoting is needed.
If a temporary launcher script is created:
  • Place it in an ignored temp/logs folder when possible, such as
    .tmp/localhost/
    ,
    tmp/
    , or another repo-approved local log folder.
  • Avoid committing it unless intentionally added as repo tooling.
  • Clean it up when no longer needed, or explain why it remains.
This example creates a temporary launcher file, sets environment variables without printing secrets, redirects logs, polls readiness, and fails fast after timeout with a safe log tail.
powershell
$app = Resolve-Path .
$port = 3000
$url = "http://127.0.0.1:$port/health"
$runDir = Join-Path $app '.tmp/localhost'
New-Item -ItemType Directory -Force -Path $runDir | Out-Null

$launcher = Join-Path $runDir 'dev-server.launch.ps1'
$log = Join-Path $runDir 'dev-server.out.log'
$err = Join-Path $runDir 'dev-server.err.log'

$conn = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
if ($conn) {
  try {
    Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null
    [pscustomobject]@{ Ready = $true; Url = $url; ReusedProcessId = $conn.OwningProcess }
    return
  } catch {
    Get-Process -Id $conn.OwningProcess | Select-Object Id,ProcessName,Path
    throw "Port $port is already listening but health failed. Ask before killing the owner."
  }
}

$processEnv = [Environment]::GetEnvironmentVariables("Process")
if ($processEnv.Contains("Path") -and $processEnv.Contains("PATH")) {
  [Environment]::SetEnvironmentVariable("PATH", $null, "Process")
}

$npm = (Get-Command npm.cmd -ErrorAction Stop).Source

@"
`$ErrorActionPreference = 'Stop'
Set-Location -LiteralPath '$app'
当启动逻辑包含引号、
#
、
=
、
$
、JSON、
.IndexOf("=")
、
.StartsWith("#")
、环境解析或多行脚本逻辑时,优先使用临时
.ps1
启动器脚本。避免在
Start-Process -ArgumentList
中使用深度嵌套的单行PowerShell字符串。
良好模式:
  • 当明确需要交互式可见窗口时,编写临时
    .ps1
    启动器脚本,并使用
    Start-Process powershell.exe -ArgumentList @("-NoExit", "-ExecutionPolicy", "Bypass", "-File", "<launcher.ps1>")
    调用它。
  • 对于自动化Agent启动,使用
    Start-Process powershell.exe -ArgumentList @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $launcher)
    ,并添加
    -WindowStyle Hidden
    和重定向日志。
  • 仅将
    Start-Job
    用于短期后台设置,而非持久化服务器管理,除非日志/进程生命周期清晰。
  • 仅当不需要嵌套引号时,使用简单的
    cmd /c
    或PowerShell命令。
如果创建了临时启动器脚本:
  • 尽可能将其放置在被忽略的临时/日志文件夹中,例如
    .tmp/localhost/
    、
    tmp/
    或其他仓库认可的本地日志文件夹。
  • 除非有意将其添加为仓库工具,否则请勿提交。
  • 不再需要时清理它,或说明保留的原因。
此示例创建临时启动器文件,设置环境变量时不打印机密信息,重定向日志,轮询就绪状态,并在超时后快速失败并返回安全的日志尾部内容。
powershell
$app = Resolve-Path .
$port = 3000
$url = "http://127.0.0.1:$port/health"
$runDir = Join-Path $app '.tmp/localhost'
New-Item -ItemType Directory -Force -Path $runDir | Out-Null

$launcher = Join-Path $runDir 'dev-server.launch.ps1'
$log = Join-Path $runDir 'dev-server.out.log'
$err = Join-Path $runDir 'dev-server.err.log'

$conn = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
if ($conn) {
  try {
    Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null
    [pscustomobject]@{ Ready = $true; Url = $url; ReusedProcessId = $conn.OwningProcess }
    return
  } catch {
    Get-Process -Id $conn.OwningProcess | Select-Object Id,ProcessName,Path
    throw "Port $port is already listening but health failed. Ask before killing the owner."
  }
}

$processEnv = [Environment]::GetEnvironmentVariables("Process")
if ($processEnv.Contains("Path") -and $processEnv.Contains("PATH")) {
  [Environment]::SetEnvironmentVariable("PATH", $null, "Process")
}

$npm = (Get-Command npm.cmd -ErrorAction Stop).Source

@"
`$ErrorActionPreference = 'Stop'
Set-Location -LiteralPath '$app'

Set required non-secret dev env values here. Never print secrets.

Set required non-secret dev env values here. Never print secrets.

$env:NODE_ENV = 'development' 
$env:HOST = '127.0.0.1' `$env:PORT = '$port'
& '$npm' run dev "@ | Set-Content -LiteralPath $launcher -Encoding UTF8
$proc = Start-Process -FilePath 'powershell.exe'
  -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $launcher)
-WorkingDirectory $app
  -RedirectStandardOutput $log
-RedirectStandardError $err
  -WindowStyle Hidden
-PassThru
$deadline = (Get-Date).AddSeconds(60) do { Start-Sleep -Seconds 2 try { Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null $ready = $true } catch { $tcp = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 $ready = [bool]$tcp } } until ($ready -or (Get-Date) -gt $deadline)
if (-not $ready) { $tail = @() foreach ($path in @($log, $err)) { if (Test-Path $path) { $tail += Get-Content -LiteralPath $path -Tail 40 } } $tcp = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 $procState = Get-Process -Id $proc.Id -ErrorAction SilentlyContinue | Select-Object Id,ProcessName,HasExited [pscustomobject]@{ Ready = $false Url = $url CommandAttempted = "npm run dev" ProcessStatus = $procState PortStatus = $tcp SafeLogTail = ($tail -join "`n") NextManualAction = "Inspect sanitized logs and run the documented command manually if needed." } return }
[pscustomobject]@{ Ready = $ready Url = $url ProcessId = $proc.Id Stdout = $log Stderr = $err }

Replace `npm run dev` with the project's actual working command. Keep sensitive values out of the launcher body when possible; prefer reading existing local `.env` through the app's normal config loader instead of echoing env values.

Avoid this fragile nested-quote anti-pattern:

```powershell
Start-Process powershell -ArgumentList "-Command", "<large quoted script with `$line.IndexOf("=")` and `$line.StartsWith("#")`>"
Python localhost apps need the same quoting discipline, especially when the repo path contains spaces:
powershell
$app = Resolve-Path .
$server = Join-Path $app 'webapp/server.py'
$python = (Get-Command python.exe -ErrorAction SilentlyContinue).Source
if (-not $python) { $python = (Get-Command py.exe -ErrorAction SilentlyContinue).Source }
$env:NODE_ENV = 'development' 
$env:HOST = '127.0.0.1' `$env:PORT = '$port'
& '$npm' run dev "@ | Set-Content -LiteralPath $launcher -Encoding UTF8
$proc = Start-Process -FilePath 'powershell.exe'
  -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $launcher)
-WorkingDirectory $app
  -RedirectStandardOutput $log
-RedirectStandardError $err
  -WindowStyle Hidden
-PassThru
$deadline = (Get-Date).AddSeconds(60) do { Start-Sleep -Seconds 2 try { Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null $ready = $true } catch { $tcp = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 $ready = [bool]$tcp } } until ($ready -or (Get-Date) -gt $deadline)
if (-not $ready) { $tail = @() foreach ($path in @($log, $err)) { if (Test-Path $path) { $tail += Get-Content -LiteralPath $path -Tail 40 } } $tcp = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1 $procState = Get-Process -Id $proc.Id -ErrorAction SilentlyContinue | Select-Object Id,ProcessName,HasExited [pscustomobject]@{ Ready = $false Url = $url CommandAttempted = "npm run dev" ProcessStatus = $procState PortStatus = $tcp SafeLogTail = ($tail -join "`n") NextManualAction = "Inspect sanitized logs and run the documented command manually if needed." } return }
[pscustomobject]@{ Ready = $ready Url = $url ProcessId = $proc.Id Stdout = $log Stderr = $err }

将`npm run dev`替换为项目实际有效的命令。尽可能避免在启动器主体中包含敏感值;优先通过应用的常规配置加载器读取现有本地`.env`文件,而非回显环境变量值。

避免以下脆弱的嵌套引号反模式:

```powershell
Start-Process powershell -ArgumentList "-Command", "<large quoted script with `$line.IndexOf("=")` and `$line.StartsWith("#")`>"
Python本地主机应用同样需要遵循引号规范,尤其是当仓库路径包含空格时:
powershell
$app = Resolve-Path .
$server = Join-Path $app 'webapp/server.py'
$python = (Get-Command python.exe -ErrorAction SilentlyContinue).Source
if (-not $python) { $python = (Get-Command py.exe -ErrorAction SilentlyContinue).Source }

If PATH lookup fails, use the current agent/platform dependency locator to find a bundled Python,

If PATH lookup fails, use the current agent/platform dependency locator to find a bundled Python,

then assign that discovered absolute python.exe path to $python.

then assign that discovered absolute python.exe path to $python.

if (-not $python) { throw 'No Python runtime was found on PATH or through the current platform runtime discovery.' }
$port = 8765 $url = "http://localhost:$port" $log = Join-Path $app 'python-server.log' $err = Join-Path $app 'python-server.err.log'
$argumentString = "
"$server
" --host 127.0.0.1 --port $port" $proc = Start-Process -FilePath $python
  -ArgumentList $argumentString
-WorkingDirectory $app
  -RedirectStandardOutput $log
-RedirectStandardError $err
  -WindowStyle Hidden
-PassThru
$deadline = (Get-Date).AddSeconds(60) do { Start-Sleep -Seconds 2 try { Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null $ready = $true } catch { $ready = $false } } until ($ready -or (Get-Date) -gt $deadline)
[pscustomobject]@{ Ready = $ready Url = $url ProcessId = $proc.Id Stdout = $log Stderr = $err }

If `python.exe` and `py.exe` are unavailable, substitute a discovered platform-provided Python executable for `$python` rather than hardcoding a user-specific path in reusable instructions.
if (-not $python) { throw 'No Python runtime was found on PATH or through the current platform runtime discovery.' }
$port = 8765 $url = "http://localhost:$port" $log = Join-Path $app 'python-server.log' $err = Join-Path $app 'python-server.err.log'
$argumentString = "
"$server
" --host 127.0.0.1 --port $port" $proc = Start-Process -FilePath $python
  -ArgumentList $argumentString
-WorkingDirectory $app
  -RedirectStandardOutput $log
-RedirectStandardError $err
  -WindowStyle Hidden
-PassThru
$deadline = (Get-Date).AddSeconds(60) do { Start-Sleep -Seconds 2 try { Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 5 | Out-Null $ready = $true } catch { $ready = $false } } until ($ready -or (Get-Date) -gt $deadline)
[pscustomobject]@{ Ready = $ready Url = $url ProcessId = $proc.Id Stdout = $log Stderr = $err }

如果`python.exe`和`py.exe`不可用,请将发现的平台提供的Python可执行文件替换为`$python`,而非在可复用指令中硬编码用户特定路径。

7. Verify from logs and HTTP

7. 通过日志和HTTP验证

powershell
Get-Content -Tail 40 .\.tmp\localhost\dev-server.out.log
Get-Content -Tail 40 .\.tmp\localhost\dev-server.err.log
Invoke-WebRequest -Uri 'http://localhost:3000' -UseBasicParsing -TimeoutSec 15
Prefer a documented health endpoint when available, such as:
text
http://localhost:3000/health
http://localhost:8000/api/health
Treat setup as incomplete until the HTTP check succeeds or the user explicitly accepts a partial result.
powershell
Get-Content -Tail 40 .\.tmp\localhost\dev-server.out.log
Get-Content -Tail 40 .\.tmp\localhost\dev-server.err.log
Invoke-WebRequest -Uri 'http://localhost:3000' -UseBasicParsing -TimeoutSec 15
如果有文档记录的健康端点,请优先使用,例如:
text
http://localhost:3000/health
http://localhost:8000/api/health
在HTTP检查成功或用户明确接受部分结果前,请勿认为设置已完成。

Log Handling Rules

日志处理规则

  • Redirect stdout/stderr to local logs for server startup diagnosis.
  • Tail only a small safe excerpt, for example the last 30-80 lines.
  • Do not print secrets: DATABASE_URL, OAuth secrets, tokens, cookies, callback URLs with query params, launch tokens, private customer/profile/pricing data, generated quote contents, or raw private payloads.
  • If logs may contain secrets, sanitize or report only safe categories such as "database connection error", "missing env var name", "port already bound", "migration failed", or "syntax error in launcher wrapper".
  • 将stdout/stderr重定向到本地日志,用于服务器启动诊断。
  • 仅提取少量安全的日志片段,例如最后30-80行。
  • 请勿打印机密信息:DATABASE_URL、OAuth密钥、令牌、Cookie、带查询参数的回调URL、启动令牌、私有客户/配置文件/定价数据、生成的报价内容或原始私有负载。
  • 如果日志可能包含机密信息,请清理或仅报告安全类别,例如“数据库连接错误”、“缺少环境变量名称”、“端口已绑定”、“迁移失败”或“启动器包装器语法错误”。

Windows Failure Patterns

Windows故障模式

PowerShell execution policy blocks
.ps1

PowerShell执行策略阻止
.ps1
脚本

Use this only to diagnose the script itself:
powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\start-local-dev.ps1
If the script still fails, stop retrying it and run the underlying start command directly.
仅在诊断脚本本身时使用此方法:
powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\start-local-dev.ps1
如果脚本仍然失败,请停止重试,直接运行底层启动命令。

Corepack or OneDrive
.corepack
EPERM

Corepack或OneDrive
.corepack
路径的
EPERM
错误

If Corepack-managed launch fails on a
.corepack
path, bypass Corepack and call the installed package-manager binary directly, such as the
pnpm.cmd
returned by
Get-Command pnpm.cmd
.
如果Corepack管理的启动在
.corepack
路径上失败,请绕过Corepack,直接调用已安装的包管理器二进制文件,例如
Get-Command pnpm.cmd
返回的
pnpm.cmd
。

Duplicate
Path
and
PATH
environment keys

重复的
Path
和
PATH
环境变量键

On Windows,
Start-Process
can fail with an error like
Item has already been added. Key in dictionary: 'Path' Key being added: 'PATH'
when the current process environment contains both
Path
and
PATH
. Normalize the duplicate process key before launching the server:
powershell
$processEnv = [Environment]::GetEnvironmentVariables("Process")
if ($processEnv.Contains("Path") -and $processEnv.Contains("PATH")) {
  [Environment]::SetEnvironmentVariable("PATH", $null, "Process")
}
Do this only for the current process before
Start-Process
; do not edit machine or user environment variables for this workaround.
在Windows上,当当前进程环境同时包含
Path
和
PATH
时,
Start-Process
可能会失败并显示类似
Item has already been added. Key in dictionary: 'Path' Key being added: 'PATH'
的错误。在启动服务器前,请规范化重复的进程键:
powershell
$processEnv = [Environment]::GetEnvironmentVariables("Process")
if ($processEnv.Contains("Path") -and $processEnv.Contains("PATH")) {
  [Environment]::SetEnvironmentVariable("PATH", $null, "Process")
}
仅在
Start-Process
前针对当前进程执行此操作;请勿为解决此问题而编辑机器或用户环境变量。

Fragile nested PowerShell quoting

脆弱的嵌套PowerShell引号

Avoid deeply nested one-line PowerShell strings inside
Start-Process -ArgumentList
when the command contains quotes,
#
,
=
,
$
, JSON,
.IndexOf("=")
,
.StartsWith("#")
, env parsing, or multiline script logic. Quote loss inside nested command strings can turn valid expressions into invalid parse fragments such as
$line.IndexOf(=)
or
$line.StartsWith(#)
.
Prefer the temporary
.ps1
launcher pattern above and call it through
-File
. Never rely only on
Start-Process
exit state as proof the app is running.
当命令包含引号、
#
、
=
、
$
、JSON、
.IndexOf("=")
、
.StartsWith("#")
、环境解析或多行脚本逻辑时,避免在
Start-Process -ArgumentList
中使用深度嵌套的单行PowerShell字符串。嵌套命令字符串中的引号丢失可能会将有效表达式转换为无效的解析片段,例如
$line.IndexOf(=)
或
$line.StartsWith(#)
。
优先使用上述临时
.ps1
启动器模式,并通过
-File
调用它。绝不能仅依赖
Start-Process
的退出状态来证明应用正在运行。

Sandbox
spawn EPERM

沙箱
spawn EPERM
错误

If the dev server fails inside an agent sandbox with
spawn EPERM
, request elevated/unsandboxed execution if the environment supports it. Do not keep retrying the same command inside the same failing sandbox.
如果开发服务器在Agent沙箱中因
spawn EPERM
失败,当环境支持时,请请求升级/非沙箱执行。请勿在同一失败沙箱中重复运行相同命令。

Codex sandbox background process does not persist

Codex沙箱后台进程无法持久

In Codex sandboxed shells, background localhost servers may exit or be killed when the shell command returns. If the user needs the dev server to keep running after the command finishes, relaunch it with
sandbox_permissions: require_escalated
when available, then repeat the same log and HTTP health verification. Report that the escalation is for local process persistence, not for external network exposure.
Even when a sandboxed background launch appears to work while the shell command is still running, do not claim the service is persistent until a follow-up port or HTTP check succeeds after that shell command has returned.
在Codex沙箱Shell中,当Shell命令返回后,后台本地主机服务器可能会退出或被终止。如果用户需要开发服务器在命令完成后继续运行,请在可用时使用
sandbox_permissions: require_escalated
重新启动,然后重复相同的日志和HTTP健康验证。请说明升级是为了本地进程持久化,而非外部网络暴露。
即使沙箱后台启动在Shell命令运行期间看似正常,也请勿声称服务持续运行,除非在Shell命令返回后,后续端口或HTTP检查成功。

Interrupted command left orphaned child processes

中断命令留下孤儿子进程

After a user interrupts a long localhost, validation, package-manager, or test command, immediately inspect likely child processes before retrying. Look for local
python
,
pip
,
node
,
npm
,
pnpm
,
yarn
,
bun
, test-runner, and dev-server processes that still own the target port or continue consuming CPU.
On Windows, start with bounded, read-only process and port checks:
powershell
Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 5
Get-Process python,pip,node,npm,pnpm,yarn,bun -ErrorAction SilentlyContinue | Select-Object Id,ProcessName,CPU,Path
Do not kill unrelated user processes. Stop a process only when it is clearly from the current agent run or after the user approves the specific PID/process name. After stopping a stale process, re-check the port or health endpoint with a short timeout before restarting.
用户中断长期运行的本地主机、验证、包管理器或测试命令后,请立即检查可能的子进程,然后再重试。查找仍占用目标端口或持续消耗CPU的本地
python
、
pip
、
node
、
npm
、
pnpm
、
yarn
、
bun
、测试运行器和开发服务器进程。
在Windows上,从有限的只读进程和端口检查开始:
powershell
Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Select-Object -First 5
Get-Process python,pip,node,npm,pnpm,yarn,bun -ErrorAction SilentlyContinue | Select-Object Id,ProcessName,CPU,Path
请勿终止无关的用户进程。仅当进程明确属于本次Agent运行,或用户批准特定PID/进程名称时,才停止该进程。停止陈旧进程后,请在重启前通过短超时重新检查端口或健康端点。

Port conflict

端口冲突

If the target port is already bound, inspect the owning process. Reuse, stop, or change port only after understanding whether the process is the same app.
如果目标端口已被绑定,请检查占用进程。仅在了解进程是否为同一应用后,再选择复用、停止或更改端口。

Process exits immediately with empty logs

进程立即退出且日志为空

Re-run the exact command in the foreground with the real shell and capture stdout/stderr directly. Empty redirected logs often mean the wrapper process died before the app started.
在真实Shell的前台重新运行确切命令,并直接捕获stdout/stderr。空的重定向日志通常意味着包装进程在应用启动前已终止。

Local UAT Launcher Checklist

本地UAT启动器检查清单

For a two-server local UAT such as a platform API plus an app:
  1. Start dependency services first, such as Docker/Postgres.
  2. Run DB preflight before migrations.
  3. Run migrations before app start.
  4. Start app servers separately.
  5. Health-check each URL independently.
  6. Use
    127.0.0.1
    consistently if the project requires it.
  7. Return a compact status block with dependency status, app server status, health status, URLs, and what remains manual.
对于双服务器本地UAT(例如平台API加应用):
  1. 先启动依赖服务,例如Docker/Postgres。
  2. 在迁移前运行数据库预检。
  3. 在应用启动前运行迁移。
  4. 单独启动应用服务器。
  5. 独立检查每个URL的健康状态。
  6. 如果项目要求,请一致使用
    127.0.0.1
    。
  7. 返回包含依赖状态、应用服务器状态、健康状态、URL以及剩余手动操作的紧凑状态块。

Anti-patterns

反模式

Avoid:
  • running a persistent server in the foreground and waiting indefinitely.
  • nested PowerShell command strings with complex quotes.
  • assuming successful process launch means server is ready.
  • restarting a server repeatedly without checking if the port is already bound.
  • printing full env or DB URLs during diagnosis.
避免:
  • 在前台运行持久化服务器并无限期等待。
  • 使用带有复杂引号的嵌套PowerShell命令字符串。
  • 假设进程启动成功意味着服务器已就绪。
  • 在不检查端口是否已绑定的情况下重复重启服务器。
  • 在诊断期间打印完整环境或数据库URL。

Reporting

报告

When finishing localhost setup, include:
  • dependency status, when dependency services were part of the task.
  • app server status.
  • health status and URL checked.
  • the exact command that worked.
  • whether a workaround was needed for execution policy, Corepack, sandbox spawning, package-manager path, port conflicts, or PowerShell launcher safety.
  • where stdout/stderr logs live.
  • any remaining manual steps.
Use this compact format:
markdown
undefined
完成本地主机设置时,请包含:
  • 依赖状态(当依赖服务属于任务内容时)。
  • 应用服务器状态。
  • 健康状态和检查的URL。
  • 有效的确切命令。
  • 是否需要针对执行策略、Corepack、沙箱生成、包管理器路径、端口冲突或PowerShell启动器安全使用解决方法。
  • stdout/stderr日志的位置。
  • 任何剩余的手动步骤。
使用以下紧凑格式:
markdown
undefined

Done

完成

Status

状态

  • Dependencies: Up / Not checked / Not required / Blocked.
  • App server: Up / Not up / Partially started.
  • Health: Passing / Failing / Timed out.
  • URLs: <urls checked>.
  • Working command:
    <command>
    .
  • 依赖项:已启动 / 未检查 / 不需要 / 阻塞。
  • 应用服务器:已启动 / 未启动 / 部分启动。
  • 健康状态:通过 / 失败 / 超时。
  • 检查的URL:<urls checked>。
  • 有效命令:
    <command>
    。

Notes

说明

  • Workaround used: <none / details>.
  • Logs: <paths>.
  • Manual remaining: <anything unresolved>.
undefined
  • 使用的解决方法:<无 / 详细信息>。
  • 日志:<路径>。
  • 剩余手动操作:<未解决的内容>。
undefined

Quality Checks

质量检查

Before finalising:
  • Confirm the app root.
  • Confirm the intended port.
  • Confirm the actual command used.
  • Confirm logs were inspected if the process was detached.
  • Confirm HTTP verification was attempted.
  • Do not pretend the service is reachable if the HTTP check failed.
完成前:
  • 确认应用根目录。
  • 确认预期端口。
  • 确认使用的实际命令。
  • 如果进程是分离式启动,请确认已检查日志。
  • 确认已尝试HTTP验证。
  • 如果HTTP检查失败,请不要声称服务可访问。