check-plain-env

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Check Plain Env

检查Plain环境

Always use the skill
load-plain-reference
to retrieve the ***plain syntax rules — but only if you haven't done so yet.
This skill answers one question: **does the host machine have everything the *plain project needs to render and test? It reads the project, derives the requirement list, probes the machine, and returns a report. It never installs anything itself — that decision belongs to the user.
请始终使用
load-plain-reference
技能获取***plain语法规则——但仅在尚未获取过的情况下执行此操作。
该技能旨在回答一个问题:主机是否具备*plain项目渲染和测试所需的全部环境?** 它会读取项目内容、推导需求列表、探测主机环境并返回报告。该技能本身不会安装任何组件——安装决策由用户自行决定。

When to run

何时运行

  • **First time you open a *plain project on a new machine — before the first
    codeplain <module>.plain
    or
    ./test_scripts/run_unittests*.sh
    invocation. This is the most common case.
  • At the start of
    forge-plain
    Phase 3 environment verification
    forge-plain
    historically did this inline; delegate to this skill instead so the same check runs the same way everywhere.
  • After
    add-feature
    — when the new feature brought in a new dependency (a new framework, a new service, a new package manager) the project didn't need before.
  • Before a real render — alongside
    plain-healthcheck
    .
    plain-healthcheck
    answers "are the specs renderable?"; this skill answers "can this machine render them?". Both should pass.
  • Onboarding — when a teammate (or CI runner, or fresh dev container) is about to start using the project.
  • Debugging a confusing failure — when a test script exits with "command not found", "module not found", "could not connect", or similar before any test runs.
  • On demand — whenever the user asks "what do I need to install for this project?".
This skill is read-only and observational. It does not edit
.plain
files, scripts, or configs, and it never invokes install commands on the user's behalf.
  • 首次在新机器上打开*plain项目时**——在首次执行
    codeplain <module>.plain
    ./test_scripts/run_unittests*.sh
    之前。这是最常见的使用场景。
  • forge-plain
    第三阶段环境验证开始时
    ——
    forge-plain
    过去曾内置此检查;现在请委托给该技能,确保所有环境检查的逻辑一致。
  • 执行
    add-feature
    之后
    ——当新功能引入了项目之前不需要的新依赖(如新框架、新服务、新包管理器)时。
  • 正式渲染之前——与
    plain-healthcheck
    配合使用。
    plain-healthcheck
    用于验证“规格是否可渲染”;而该技能用于验证“当前机器是否能够渲染这些规格”。两者都需通过检查。
  • 新成员入职时——当团队成员(或CI运行器、全新开发容器)准备开始使用项目时。
  • 排查模糊故障时——当测试脚本在运行任何测试之前就因“命令未找到”“模块未找到”“无法连接”等类似错误退出时。
  • 按需运行——每当用户询问“我需要为这个项目安装什么?”时。
该技能为只读观测型工具。它不会编辑
.plain
文件、脚本或配置,也绝不会代表用户执行安装命令。

What this skill does NOT do

该技能不做什么

  • It does not install anything. It only suggests install commands and lets the user run them.
  • It does not generate scripts, modify
    config.yaml
    , or change project files. Use
    implement-*-testing-script
    ,
    init-config-file
    , etc. for that.
  • It does not start services (databases, brokers, Docker daemons). It only checks whether the right binaries and (optionally) running endpoints are reachable.
  • It does not validate the specs themselves (syntax, dry-run, complexity). Use
    plain-healthcheck
    for that — the two skills are complementary.
  • It does not print secrets. Check whether an env var is set (e.g.
    printenv FOO >/dev/null && echo set || echo missing
    ), never echo its value.
  • 不会安装任何组件。仅会提供安装建议命令,由用户自行决定是否执行。
  • 不会生成脚本、修改
    config.yaml
    或更改项目文件。如需此类操作,请使用
    implement-*-testing-script
    init-config-file
    等技能。
  • 不会启动服务(如数据库、消息队列、Docker守护进程)。仅会检查相应的二进制文件是否存在,以及(可选)运行中的端点是否可达。
  • 不会验证规格本身(语法、试运行、复杂度)。此类操作请使用
    plain-healthcheck
    ——这两个技能互为补充。
  • 不会打印敏感信息。仅会检查环境变量是否已设置(例如:
    printenv FOO >/dev/null && echo set || echo missing
    ),绝不会输出其具体值。

Workflow

工作流程

The skill is a derive → probe → report pass. It does not stop at the first missing tool; it surfaces every gap so the user gets a single complete shopping list.
该技能遵循推导→探测→报告的流程。它不会在检测到第一个缺失工具时停止,而是会列出所有缺口,让用户一次性获取完整的待安装清单。

Step 1 — Inventory the project

步骤1 — 清点项目内容

  1. Detect the host OS first. Run
    uname -s 2>/dev/null || echo "$OS"
    . Use the result to (a) pick the right script extensions to inspect (
    .sh
    vs
    .ps1
    ) and (b) pick the right install commands later (Homebrew, apt, dnf, pacman, choco, scoop, winget).
  2. List every
    .plain
    file
    in the repo root and in any subdirectory that contains them. Note which are top modules (not
    requires
    -ed by anything) and which are import modules (under
    template/
    ).
  3. List every
    config.yaml
    in the repo and read each one. Note the
    *-script
    keys it sets and the values they point at.
  4. List every script under
    test_scripts/
    (both
    .sh
    and
    .ps1
    — projects can ship both).
  5. List every file under
    resources/
    if the directory exists. Schemas and protocol files there often imply running services (e.g. a Postgres
    .sql
    schema implies a Postgres server).
  6. Print a one-line inventory summary, e.g.
    Detected: 2 top modules (backend/api.plain, frontend/web.plain), 2 config.yaml(s), 4 test_scripts, 3 resources. Host: Darwin.
  1. 先检测主机操作系统。执行
    uname -s 2>/dev/null || echo "$OS"
    。根据检测结果:(a)选择要检查的正确脚本扩展名(
    .sh
    .ps1
    );(b)后续选择对应的操作系统专属安装命令(如Homebrew、apt、dnf、pacman、choco、scoop、winget)。
  2. 列出仓库根目录及所有包含
    .plain
    文件的子目录中的每一个
    .plain
    文件
    。记录哪些是顶层模块(未被任何模块
    requires
    引用),哪些是导入模块(位于
    template/
    目录下)。
  3. 列出仓库中的每一个
    config.yaml
    文件并读取内容
    。记录其中设置的
    *-script
    键及其指向的值。
  4. 列出
    test_scripts/
    目录下的所有脚本
    (包括
    .sh
    .ps1
    ——项目可同时提供两种脚本)。
  5. 如果
    resources/
    目录存在,列出其中的所有文件
    。该目录下的 schema 和协议文件通常意味着需要运行相应服务(例如Postgres的
    .sql
    schema意味着需要Postgres服务器)。
  6. 打印一行清点摘要,例如:
    检测到:2个顶层模块(backend/api.plain、frontend/web.plain),2个config.yaml文件,4个测试脚本,3个资源文件。主机系统:Darwin。

Step 2 — Derive the requirement list (at runtime, from what the project actually says)

步骤2 — 推导需求列表(从项目实际内容实时生成)

The requirement list is not pre-baked into this skill. There is no catalog of "things to always check". The list is derived for each project from the project itself, by reading the specs and scripts in front of you and classifying every signal into one of the categories below.
需求列表并非预先内置在该技能中。不存在“始终需要检查的内容”清单。需求列表需针对每个项目,通过读取当前项目的规格和脚本,将每个信号归类到以下类别中实时生成。

What to check vs. what not to check

检查范围与排除范围

The single most important rule:
Check only the layers a package manager cannot install. Anything
pip install -r requirements.txt
,
npm ci
,
mvn install
,
cargo fetch
,
go mod download
,
bundle install
,
composer install
, etc. would resolve is out of scope for this skill. It will be installed by the project's own scripts the moment they run. Checking it here is wasted work and creates false-negative reports the moment the manifest changes.
Concretely:
  • Do NOT check individual language packages — not
    torch
    , not
    requests
    , not
    numpy
    , not
    FastAPI
    , not
    express
    , not
    react
    , not a specific JAR in
    pom.xml
    , not a specific gem in
    Gemfile
    , not a specific crate in
    Cargo.toml
    . The language's package manager handles all of it. The same rule applies in every language — Python, Node.js, Java, Go, Rust, Ruby, PHP, .NET, Dart, etc.
  • Do check the layers below the package manager, which fall into four categories. Build the requirement list at runtime by walking through each category and adding only what the project actually needs.
最重要的规则:
仅检查包管理器无法安装的层级。任何可通过
pip install -r requirements.txt
npm ci
mvn install
cargo fetch
go mod download
bundle install
composer install
等命令解决的依赖均不在本技能的检查范围内。这些依赖会在项目脚本运行时自动安装。在此处检查它们纯属浪费精力,且会在清单变更时产生误报。
具体说明:
  • 请勿检查单个语言包——包括
    torch
    requests
    numpy
    FastAPI
    express
    react
    pom.xml
    中的特定JAR包,
    Gemfile
    中的特定gem,
    Cargo.toml
    中的特定crate等。这些均由对应语言的包管理器处理。该规则适用于所有语言——Python、Node.js、Java、Go、Rust、Ruby、PHP、.NET、Dart等。
  • 请检查包管理器之下的层级,分为四类。通过遍历每个类别,仅添加项目实际需要的内容,实时构建需求列表。

Category 1 — Language toolchains and their package managers

类别1 — 语言工具链及其包管理器

For each language the project uses, the toolchain must be on the host — the package manager cannot install itself. Decide which toolchains apply by reading the specs and scripts:
  • Signals in
    .plain
    files
    : phrases like
    should be in Python
    ,
    should be in Java
    ,
    should be in Go
    in
    ***implementation reqs***
    . Find the language; ignore the framework (the framework is a package, not a toolchain).
  • Signals in
    test_scripts/
    (more reliable, because scripts are the executable contract): which interpreter / build tool is invoked at the top level.
    python3
    /
    pip
    → Python toolchain.
    node
    /
    npm
    /
    pnpm
    /
    yarn
    → Node.js toolchain.
    mvn
    /
    gradle
    → JDK + Maven/Gradle.
    go
    → Go toolchain.
    cargo
    → Rust toolchain.
    dotnet
    → .NET SDK.
    ruby
    /
    bundle
    → Ruby + Bundler.
    php
    /
    composer
    → PHP + Composer.
    dart
    /
    flutter
    → Dart/Flutter SDK.
For each detected toolchain, probe both the interpreter/compiler and its package manager:
  • Python →
    python3 --version
    +
    pip --version
    .
  • Node.js →
    node --version
    +
    npm --version
    (or
    pnpm
    /
    yarn
    if the scripts use them).
  • Java →
    java -version
    +
    javac -version
    +
    mvn -version
    (or
    gradle --version
    ).
  • Go →
    go version
    .
  • Rust →
    cargo --version
    +
    rustc --version
    .
  • .NET →
    dotnet --version
    .
  • Ruby →
    ruby --version
    +
    bundle --version
    .
  • PHP →
    php --version
    +
    composer --version
    .
  • Flutter / Dart →
    flutter --version
    +
    dart --version
    .
That's where the language-package check stops. Once
python3
and
pip
are on the host,
pip install -r requirements.txt
will handle
torch
,
numpy
,
requests
, etc. when the test script runs. Don't probe for them here.
对于项目使用的每种语言,主机上必须具备对应的工具链——包管理器无法自行安装。通过读取规格和脚本判断适用的工具链:
  • .plain
    文件中的信号
    ***implementation reqs***
    部分中类似
    should be in Python
    should be in Java
    should be in Go
    的表述。识别出语言即可;忽略框架(框架属于包,而非工具链)。
  • test_scripts/
    中的信号
    (更可靠,因为脚本是可执行的契约):顶层调用的解释器/构建工具。
    python3
    /
    pip
    →Python工具链;
    node
    /
    npm
    /
    pnpm
    /
    yarn
    →Node.js工具链;
    mvn
    /
    gradle
    →JDK + Maven/Gradle;
    go
    →Go工具链;
    cargo
    →Rust工具链;
    dotnet
    →.NET SDK;
    ruby
    /
    bundle
    →Ruby + Bundler;
    php
    /
    composer
    →PHP + Composer;
    dart
    /
    flutter
    →Dart/Flutter SDK。
针对每个检测到的工具链,同时探测解释器/编译器及其包管理器:
  • Python →
    python3 --version
    +
    pip --version
  • Node.js →
    node --version
    +
    npm --version
    (如果脚本使用
    pnpm
    /
    yarn
    则替换为对应命令)
  • Java →
    java -version
    +
    javac -version
    +
    mvn -version
    (或
    gradle --version
  • Go →
    go version
  • Rust →
    cargo --version
    +
    rustc --version
  • .NET →
    dotnet --version
  • Ruby →
    ruby --version
    +
    bundle --version
  • PHP →
    php --version
    +
    composer --version
  • Flutter/Dart →
    flutter --version
    +
    dart --version
语言包检查到此为止。一旦主机上安装了
python3
pip
,当测试脚本运行时,
pip install -r requirements.txt
会自动处理
torch
numpy
requests
等依赖。无需在此处探测这些包。

Category 2 — External services

类别2 — 外部服务

Services that run as separate processes / daemons and cannot be installed by a language package manager. Identify them at runtime by reading the specs and config:
  • Signals: a
    .plain
    file names a service the implementation talks to (database, cache, queue, broker, orchestrator). A
    resources/*.sql
    schema implies a database. A
    docker-compose.yml
    (if present) lists services explicitly.
  • For each service found, probe both that its CLI is available and — when possible — that the service is reachable. "Binary present but service not running" should report as
    WARN
    , not
    FAIL
    ; the user may want to start it on demand.
No catalog — if the spec says "uses PostgreSQL" you check Postgres, if it says "uses Redis" you check Redis, if it says "uses some-niche-service" you look up its CLI on the fly and probe that. Don't pretend the list is closed.
作为独立进程/守护进程运行、无法通过语言包管理器安装的服务。通过读取规格和配置实时识别:
  • 信号
    .plain
    文件中提到实现需要对接的服务(数据库、缓存、队列、消息代理、编排器);
    resources/*.sql
    schema意味着需要数据库;如果存在
    docker-compose.yml
    ,则会明确列出服务。
  • 针对每个检测到的服务,同时探测其CLI是否可用以及(在可行的情况下)服务是否可达。“二进制文件存在但服务未运行”应标记为
    WARN
    而非
    FAIL
    ;用户可能希望按需启动服务。
无固定清单——如果规格提到“使用PostgreSQL”则检查Postgres,提到“使用Redis”则检查Redis,提到“使用某个小众服务”则实时查找其CLI并进行探测。不要假设检查范围是固定的。

Category 3 — System binaries that language packages wrap

类别3 — 语言包封装的系统二进制文件

Some language packages are thin wrappers around a system binary that
pip install
/
npm install
cannot install for you
. The package manager installs the wrapper; the wrapped binary still has to be on the host separately. This is the most commonly missed category.
Decide at runtime by reading the workflow described in the specs. If the workflow can't physically run without an external tool, that tool needs to be checked even though the language wrapper around it is in
requirements.txt
. Examples of the pattern (not an exhaustive list — derive yours from the actual project):
  • The spec describes OCR → a wrapper like
    pytesseract
    is in
    requirements.txt
    , but the host still needs the
    tesseract
    binary and the language data files.
  • The spec describes video/audio processing →
    ffmpeg-python
    is in the manifest, but the
    ffmpeg
    binary itself must be on the host.
  • The spec describes PDF extraction → a Python wrapper is in the manifest, but the
    pdftotext
    /
    pdftoppm
    binaries from poppler-utils are still required.
  • The spec describes headless-browser e2e testing → the npm package is in
    package.json
    , but the actual browser binaries (Chromium, Firefox, WebKit) must be downloaded onto the host separately.
  • The spec describes shelling out to any external CLI from generated code → that CLI must be on the host.
Heuristic for spotting Category 3: if removing the package from
requirements.txt
would still leave a binary on the host that the project depends on, the binary belongs in Category 3. If the package is the only thing the project needs, it's package-manager territory and out of scope.
Whenever the test scripts themselves invoke a non-language binary (
ffmpeg
,
psql
,
docker
,
tesseract
, ...), that binary is automatically Category 3 — the script is the executable contract. Always reconcile the spec-derived list against the scripts before probing.
有些语言包是系统二进制文件的轻量封装,而这些系统二进制文件无法通过
pip install
/
npm install
安装
。包管理器仅安装封装层,被封装的二进制文件仍需单独安装在主机上。这是最容易被遗漏的类别。
通过读取规格中描述的工作流程实时判断。如果工作流程在没有外部工具的情况下无法实际运行,则该工具需要被检查,即使其语言封装包已包含在
requirements.txt
中。以下是此类场景的模式示例(非 exhaustive 列表——需从实际项目中推导):
  • 规格描述了OCR功能→
    requirements.txt
    中包含
    pytesseract
    封装包,但主机仍需安装
    tesseract
    二进制文件和语言数据文件。
  • 规格描述了音视频处理→
    manifest
    中包含
    ffmpeg-python
    ,但主机仍需安装
    ffmpeg
    二进制文件。
  • 规格描述了PDF提取→
    manifest
    中包含Python封装包,但仍需安装poppler-utils提供的
    pdftotext
    /
    pdftoppm
    二进制文件。
  • 规格描述了无头浏览器端到端测试→
    package.json
    中包含npm包,但实际浏览器二进制文件(Chromium、Firefox、WebKit)仍需单独下载到主机。
  • 规格描述了从生成的代码中调用外部CLI→该CLI必须已安装在主机上。
识别类别3的启发式规则:如果从
requirements.txt
中移除某个包后,项目仍依赖主机上的某个二进制文件,则该二进制文件属于类别3。如果项目仅需要该包本身,则属于包管理器的处理范围,不在本技能的检查范围内。
当测试脚本本身调用了非语言二进制文件(如
ffmpeg
psql
docker
tesseract
等),该二进制文件自动属于类别3——脚本是可执行的契约。在探测前,请始终将从规格推导的列表与脚本进行核对

Category 4 — Hardware, drivers, accelerators

类别4 — 硬件、驱动程序、加速器

Things the OS — not any package manager — must provide. The only category where the chain runs deeper than "is this binary on PATH?".
  • Signals: a spec mentions GPU acceleration, local model training/fine-tuning, real-time inference, CUDA, MPS / Apple Silicon, hardware-accelerated video encoding, etc.
  • The check is layered, and each layer fails independently. Probe each one and surface each result separately, in order, so the user sees exactly where the chain breaks:
    1. Driver present? (e.g.
      nvidia-smi
      succeeds.)
    2. Device visible? (e.g.
      nvidia-smi -L
      lists ≥ 1 GPU.)
    3. Accelerator SDK installed? (e.g.
      nvcc --version
      for the CUDA toolkit.)
    4. Acceleration libraries discoverable? (e.g. cuDNN via
      ldconfig -p \| grep libcudnn
      on Linux.)
    5. The runtime can actually see the accelerator? (e.g. a one-line Python probe through whatever framework the spec named:
      python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"
      .) This particular layer does require the language package, so run it after the test scripts have had a chance to install dependencies — or surface it as "can be verified after
      pip install
      " if dependencies aren't installed yet.
    6. Version compatibility. If the runtime reports a different CUDA major version than the toolkit, surface a
      WARN
      . Driver / toolkit / runtime version mismatches are the most common silent GPU bug.
The same shape applies to other accelerators: Apple Silicon / MPS (
uname -m
,
sw_vers
, framework probe), AMD ROCm (
rocminfo
), Intel oneAPI, etc. Look up the relevant probe at runtime from the spec's terminology.
Worked example — the GPU case:
A
.plain
file declares:
:Implementation: should fine-tune :BaseModel: on the user's local hardware using PyTorch. Training should use available GPUs when present.
What the package manager handles (out of scope for this skill):
torch
itself.
pip install -r requirements.txt
will fetch the right wheel.
What this skill must probe (in scope):
  1. The Python toolchain (Category 1):
    python3 --version
    ,
    pip --version
    .
  2. The NVIDIA driver (Category 4, layer 1):
    nvidia-smi
    .
  3. At least one GPU visible (Category 4, layer 2):
    nvidia-smi -L
    lists ≥ 1 device.
  4. CUDA toolkit (Category 4, layer 3):
    nvcc --version
    .
  5. cuDNN discoverable (Category 4, layer 4):
    ldconfig -p \| grep libcudnn
    on Linux; skip on macOS.
  6. PyTorch actually sees the GPU (Category 4, layer 5):
    python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"
    — noting this requires
    torch
    to be installed (i.e. requires the test scripts to have run their install step at least once).
  7. Version match (Category 4, layer 6): cross-check
    torch.version.cuda
    against
    nvcc --version
    . Mismatch →
    WARN
    .
The skill never asks "is
torch
installed?". That belongs to
pip
.
必须由操作系统(而非任何包管理器)提供的组件。这是唯一需要深入检查“PATH中是否存在二进制文件”之外内容的类别。
  • 信号:规格提到GPU加速、本地模型训练/微调、实时推理、CUDA、MPS/Apple Silicon、硬件加速视频编码等。
  • 检查是分层的,每层独立判断是否失败。按顺序探测每一层并单独呈现结果,以便用户准确看到故障链的断点:
    1. 驱动程序是否存在?(例如:
      nvidia-smi
      执行成功)
    2. 设备是否可见?(例如:
      nvidia-smi -L
      列出至少1个GPU)
    3. 加速器SDK是否已安装?(例如:CUDA工具包的
      nvcc --version
    4. 加速库是否可被发现?(例如:在Linux上通过
      ldconfig -p | grep libcudnn
      检查cuDNN)
    5. 运行时是否能实际识别加速器?(例如:通过规格中提到的框架执行一行Python探测代码:
      python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"
      )。这一层确实需要语言包,因此需在测试脚本有机会安装依赖后再运行;如果依赖尚未安装,则提示“可在
      pip install
      后验证”。
    6. 版本兼容性。如果运行时报告的CUDA主版本与工具包版本不一致,标记为
      WARN
      。驱动程序/工具包/运行时版本不匹配是最常见的隐性GPU故障原因。
同样的分层检查模式适用于其他加速器:Apple Silicon/MPS(
uname -m
sw_vers
、框架探测)、AMD ROCm(
rocminfo
)、Intel oneAPI等。根据规格中的术语实时查找对应的探测方法。
示例——GPU场景:
某个
.plain
文件声明:
:Implementation: should fine-tune :BaseModel: on the user's local hardware using PyTorch. Training should use available GPUs when present.
包管理器处理的内容(不在本技能检查范围内):
torch
本身。
pip install -r requirements.txt
会获取正确的wheel包。
本技能必须探测的内容(在检查范围内):
  1. Python工具链(类别1):
    python3 --version
    pip --version
  2. NVIDIA驱动程序(类别4,第1层):
    nvidia-smi
  3. 至少1个GPU可见(类别4,第2层):
    nvidia-smi -L
    列出至少1个设备
  4. CUDA工具包(类别4,第3层):
    nvcc --version
  5. cuDNN可被发现(类别4,第4层):在Linux上执行
    ldconfig -p | grep libcudnn
    ;在macOS上跳过此检查
  6. PyTorch实际识别到GPU(类别4,第5层):
    python -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)"
    ——注意这需要
    torch
    已安装(即测试脚本至少运行过一次安装步骤)
  7. 版本匹配(类别4,第6层):对比
    torch.version.cuda
    nvcc --version
    的结果。版本不匹配→标记为
    WARN
该技能绝不会检查“
torch
是否已安装”。这属于
pip
的处理范围。

Category 5 — Always required

类别5 — 始终需要检查的内容

Add these to every requirement list regardless of project:
  • codeplain
    CLI on
    PATH
    codeplain --version
    .
  • CODEPLAIN_API_KEY
    env var set
    printenv CODEPLAIN_API_KEY >/dev/null && echo set || echo missing
    (never echo the value).
  • A shell matching the testing scripts' extension (Bash for
    .sh
    , PowerShell for
    .ps1
    ).
  • git
    (the renderer uses it; almost every plain project tracks itself in git).
无论项目如何,都需将以下内容添加到需求列表中:
  • PATH
    中存在
    codeplain
    CLI——
    codeplain --version
  • 已设置
    CODEPLAIN_API_KEY
    环境变量——
    printenv CODEPLAIN_API_KEY >/dev/null && echo set || echo missing
    (绝不要输出其值)
  • 与测试脚本扩展名匹配的Shell(
    .sh
    对应Bash,
    .ps1
    对应PowerShell)
  • git
    (渲染器会用到它;几乎所有plain项目都使用git进行版本控制)

Step 3 — Probe the host

步骤3 — 探测主机环境

For every requirement the project produced in Step 2, run a check using the
terminal
tool. Capture stdout/stderr and exit code. Classify each result:
  • PASS — present and (where a version was specified) at or above the required version.
  • WARN — present but at a version that doesn't match what the project explicitly asks for (e.g. spec says Java 17, host has Java 21), or service binary present but the service itself isn't running, or a Category 4 sub-layer is mismatched against another (e.g. CUDA toolkit version doesn't match what the framework expects).
  • FAIL — missing, unreachable, or below the minimum version.
Probe in the same category order Step 2 produced them, so the report reads top-down:
  1. Category 1 — Language toolchains. Run the toolchain + package-manager probes listed in Step 2's Category 1 for the languages this project actually uses. Do not probe individual language packages.
  2. Category 5 — Codeplain and
    git
    .
    Always required, independent of the project.
    codeplain --version
    ,
    printenv CODEPLAIN_API_KEY >/dev/null
    ,
    git --version
    . Verify the shell flavor matches the scripts' extension; a
    .sh
    -only project on native Windows is a
    FAIL
    (suggest WSL).
  3. Category 2 — External services. For each service identified at runtime, probe the CLI's presence first, then — if the CLI exists — check whether the service itself is reachable. Service binary present but daemon down →
    WARN
    , not
    FAIL
    .
  4. Category 3 — System binaries that language packages wrap. For each one identified in Step 2, check the system binary is on
    PATH
    (
    which <bin>
    /
    <bin> --version
    ). The wrapper package itself isn't probed.
  5. Category 4 — Hardware, drivers, accelerators. Walk the layered probe from Step 2 in order (driver → device visibility → SDK → acceleration libs → framework-sees-it → version match), reporting each layer's result separately. Never collapse a multi-layer failure into a single "GPU not available" message — each layer has a different fix.
  6. Credentials and config holes. For every env var, dotfile, or cloud CLI login state the project implies, probe its presence without printing its value:
    printenv VAR >/dev/null && echo set || echo missing
    ,
    [ -f <path> ] && echo present || echo missing
    ,
    aws sts get-caller-identity
    /
    gcloud auth list
    /
    az account show
    for cloud SDKs.
针对步骤2中生成的每一项需求,使用
terminal
工具执行检查。捕获标准输出/标准错误和退出码。将每个结果分类:
  • PASS——组件已存在,且(如果指定了版本)版本符合或高于要求版本。
  • WARN——组件已存在,但版本与项目明确要求的版本不匹配(例如:规格要求Java 17,主机安装了Java 21),或服务二进制文件存在但服务未运行,或类别4中的某一层与其他层不匹配(例如:CUDA工具包版本与框架预期版本不匹配)。
  • FAIL——组件缺失、不可达,或版本低于最低要求。
按照步骤2生成的类别顺序进行探测,使报告从上到下逻辑清晰:
  1. 类别1 — 语言工具链。针对项目实际使用的语言,执行步骤2类别1中列出的工具链+包管理器探测命令。请勿探测单个语言包。
  2. 类别5 — Codeplain与
    git
    。始终需要检查,与项目无关。执行
    codeplain --version
    printenv CODEPLAIN_API_KEY >/dev/null
    git --version
    。验证Shell类型与脚本扩展名匹配;如果项目仅包含
    .sh
    脚本但主机是原生Windows系统,则标记为
    FAIL
    (建议使用WSL)。
  3. 类别2 — 外部服务。针对每个实时识别的服务,先探测CLI是否存在;如果CLI存在,则检查服务是否可达。服务二进制文件存在但守护进程未运行→标记为
    WARN
    而非
    FAIL
  4. 类别3 — 语言包封装的系统二进制文件。针对步骤2中识别的每个二进制文件,检查其是否在
    PATH
    中(
    which <bin>
    /
    <bin> --version
    )。不探测封装包本身。
  5. 类别4 — 硬件、驱动程序、加速器。按照步骤2中的分层探测顺序(驱动程序→设备可见性→SDK→加速库→框架识别→版本匹配)执行检查,单独报告每一层的结果。绝不要将多层故障合并为单一的“GPU不可用”消息——每一层的修复方法都不同。
  6. 凭证与配置缺口。针对项目隐含的每个环境变量、点文件或云CLI登录状态,探测其是否存在但不输出具体值:
    printenv VAR >/dev/null && echo set || echo missing
    [ -f <path> ] && echo present || echo missing
    、针对云SDK执行
    aws sts get-caller-identity
    /
    gcloud auth list
    /
    az account show

Step 4 — Report

步骤4 — 生成报告

Emit a single report with the verdict on the first line so callers can pattern-match without parsing the body:
  • PASS
    — every required item is present at an acceptable version. Follow with a one-paragraph summary listing what was checked.
  • WARN
    — everything required is present but at least one item triggered a soft warning (version mismatch, service not currently running). Follow with the numbered list of warnings.
  • FAIL
    — at least one required item is missing or below minimum version. Follow with a numbered list of every gap.
For every FAIL and WARN item, the report must include four columns:
ColumnContent
WhatThe missing tool/service/credential.
WhyWhich spec, script, or library introduced this requirement (e.g. "
backend/api.plain
says
using FastAPI
", "
test_scripts/run_unittests_python.sh
calls
pytest
").
Status"missing", "outdated (found X, need Y)", "binary present but service not running", or "env var not set".
How to installOS-specific command(s). See Install suggestions below.
Group the report into the same six probe groups used in Step 3 (toolchains, codeplain/git, services, system binaries, hardware, credentials), so the user can fix one whole layer at a time.
End the report with a one-liner reminder:
Re-run check-plain-env after installing missing items to confirm.
生成一份报告,第一行显示最终结论,以便调用方无需解析报告主体即可匹配结果:
  • PASS
    ——所有必需组件均已存在且版本符合要求。后续附上一段摘要,列出已检查的内容。
  • WARN
    ——所有必需组件均已存在,但至少有一项触发了软警告(版本不匹配、服务当前未运行等)。后续附上编号的警告列表。
  • FAIL
    ——至少有一项必需组件缺失或版本低于最低要求。后续附上编号的所有缺口列表。
对于每一项FAILWARN,报告必须包含四列:
列名内容
检查项缺失的工具/服务/凭证
原因引入该需求的规格、脚本或库(例如:"
backend/api.plain
中提到
using FastAPI
"、"
test_scripts/run_unittests_python.sh
调用了
pytest
")
状态"缺失"、"版本过时(已安装X,需要Y)"、"二进制文件存在但服务未运行"或"环境变量未设置"
安装方法操作系统专属命令。请参阅下方的安装建议
将报告按照步骤3中的六个探测组进行分组(工具链、Codeplain与git、服务、系统二进制文件、硬件、凭证),以便用户可以一次性修复整个层级的问题。
报告末尾添加一行提示:
安装缺失组件后,请重新运行check-plain-env以确认环境符合要求。

Install suggestions

安装建议

When emitting an install command, match the host OS detected in Step 1. Prefer the OS's first-party package manager. Don't suggest
curl | sh
style installs unless there is no alternative.
The tables below are a starter set of well-known install commands for the things projects most often need. They are not a list of "things to check" — that list is derived per project in Step 2. When the requirement list contains something not in these tables (e.g. a niche service, a specialty CLI), look up the canonical install command for the detected OS at the time of report generation rather than skipping the row or inventing a command.
生成安装命令时,需与步骤1中检测到的主机操作系统匹配。优先使用操作系统的官方包管理器。除非没有其他选择,否则不要建议使用
curl | sh
类的安装方式。
以下表格是项目最常需要的知名安装命令的起始集合。它们并非“需要检查的内容”列表——该列表需在步骤2中针对每个项目实时推导。当需求列表中包含表格中未列出的内容(例如小众服务、专业CLI)时,请在生成报告时查找对应操作系统的官方安装命令,不要跳过该行或自行编造命令。

macOS (Darwin)

macOS(Darwin)

RequirementSuggested install
Python 3
brew install python@3.12
Node.js
brew install node
(or
brew install nvm
for multi-version)
Go
brew install go
Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
(no Homebrew equivalent that stays current)
Java
brew install openjdk@21
then follow the post-install
sudo ln -sfn ...
step
Maven
brew install maven
Gradle
brew install gradle
PostgreSQL
brew install postgresql@16
then
brew services start postgresql@16
MySQL
brew install mysql
then
brew services start mysql
Redis
brew install redis
then
brew services start redis
DockerInstall Docker Desktop from https://docker.com/products/docker-desktop
pg_config
(psycopg)
comes with
brew install postgresql@16
Xcode CLT
xcode-select --install
codeplain
follow the install instructions at https://codeplain.ai
需求建议安装命令
Python 3
brew install python@3.12
Node.js
brew install node
(或
brew install nvm
用于多版本管理)
Go
brew install go
Rust`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
Java
brew install openjdk@21
,然后按照安装后的提示执行
sudo ln -sfn ...
步骤
Maven
brew install maven
Gradle
brew install gradle
PostgreSQL
brew install postgresql@16
,然后执行
brew services start postgresql@16
MySQL
brew install mysql
,然后执行
brew services start mysql
Redis
brew install redis
,然后执行
brew services start redis
Dockerhttps://docker.com/products/docker-desktop安装Docker Desktop
pg_config
(psycopg)
brew install postgresql@16
一同安装
Xcode CLT
xcode-select --install
codeplain
按照https://codeplain.ai上的安装说明执行

Linux (Debian/Ubuntu)

Linux(Debian/Ubuntu)

RequirementSuggested install
Python 3
sudo apt update && sudo apt install -y python3 python3-pip python3-venv
Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs
Go
sudo apt install -y golang-go
(or download from https://go.dev/dl/ for the latest)
Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Java
sudo apt install -y openjdk-21-jdk
Maven
sudo apt install -y maven
PostgreSQL
sudo apt install -y postgresql postgresql-contrib && sudo systemctl start postgresql
Redis
sudo apt install -y redis-server && sudo systemctl start redis-server
Dockerfollow https://docs.docker.com/engine/install/ubuntu/
pg_config
(psycopg)
sudo apt install -y libpq-dev
C/C++ build tools
sudo apt install -y build-essential
需求建议安装命令
Python 3
sudo apt update && sudo apt install -y python3 python3-pip python3-venv
Node.js`curl -fsSL https://deb.nodesource.com/setup_20.x
Go
sudo apt install -y golang-go
(或从https://go.dev/dl/下载最新版本)
Rust`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
Java
sudo apt install -y openjdk-21-jdk
Maven
sudo apt install -y maven
PostgreSQL
sudo apt install -y postgresql postgresql-contrib && sudo systemctl start postgresql
Redis
sudo apt install -y redis-server && sudo systemctl start redis-server
Docker按照https://docs.docker.com/engine/install/ubuntu/中的说明执行
pg_config
(psycopg)
sudo apt install -y libpq-dev
C/C++构建工具
sudo apt install -y build-essential

Linux (Fedora/RHEL)

Linux(Fedora/RHEL)

Equivalent commands with
sudo dnf install -y ...
instead of
apt
. Surface them when the host is detected as Fedora/RHEL (e.g. presence of
/etc/redhat-release
or
dnf --version
succeeding).
使用
sudo dnf install -y ...
替代apt命令。当检测到主机为Fedora/RHEL(例如存在
/etc/redhat-release
dnf --version
执行成功)时,显示这些命令。

Windows (native PowerShell)

Windows(原生PowerShell)

RequirementSuggested install
Python 3
winget install Python.Python.3.12
or
choco install python
Node.js
winget install OpenJS.NodeJS.LTS
or
choco install nodejs-lts
Go
winget install GoLang.Go
Rust
winget install Rustlang.Rustup
Java
winget install Microsoft.OpenJDK.21
PostgreSQL
winget install PostgreSQL.PostgreSQL
Docker
winget install Docker.DockerDesktop
MSVC build tools
winget install Microsoft.VisualStudio.2022.BuildTools
If the project's
test_scripts/
are
.sh
only and the host is native Windows, suggest WSL (
wsl --install
) rather than trying to make Bash scripts run under PowerShell.
需求建议安装命令
Python 3
winget install Python.Python.3.12
choco install python
Node.js
winget install OpenJS.NodeJS.LTS
choco install nodejs-lts
Go
winget install GoLang.Go
Rust
winget install Rustlang.Rustup
Java
winget install Microsoft.OpenJDK.21
PostgreSQL
winget install PostgreSQL.PostgreSQL
Docker
winget install Docker.DockerDesktop
MSVC构建工具
winget install Microsoft.VisualStudio.2022.BuildTools
如果项目的
test_scripts/
仅包含
.sh
脚本且主机是原生Windows系统,建议使用WSL
wsl --install
),而非尝试让Bash脚本在PowerShell下运行。

When you can't pick

无法确定操作系统时

When the host OS detection in Step 1 was inconclusive (e.g. an unrecognized Linux distro), include the macOS and Debian/Ubuntu commands and tell the user to adapt for their package manager. Never invent install commands for a distro you can't identify.
如果步骤1中的操作系统检测结果不明确(例如无法识别的Linux发行版),请同时提供macOS和Debian/Ubuntu的命令,并告知用户根据自己的包管理器进行调整。绝不要为无法识别的发行版编造安装命令。

Anti-patterns

反模式

  • (Hard mistake) Don't probe individual language packages. Anything
    pip install -r requirements.txt
    ,
    npm ci
    ,
    mvn install
    ,
    cargo fetch
    ,
    go mod download
    ,
    bundle install
    ,
    composer install
    , etc. would resolve is out of scope.
    torch
    ,
    requests
    ,
    numpy
    ,
    FastAPI
    ,
    express
    ,
    react
    , JARs, gems, crates — all package-manager territory. Check the toolchain (
    python3
    ,
    pip
    ,
    node
    ,
    npm
    ,
    mvn
    ,
    cargo
    , ...) and stop there. Probing the package itself creates false negatives the moment
    requirements.txt
    changes and duplicates work the test scripts will do anyway.
  • Don't stop after the directly named technologies. A spec that says "fine-tune on local hardware using PyTorch" never says "CUDA", but the workflow can't run without CUDA. Always work through Category 3 (system binaries that language packages wrap) and Category 4 (hardware/drivers) — not only the directly named runtimes. These categories are where the workflow's hidden requirements live.
  • Don't merge a chain of failures into one generic message. "GPU not available" is not a useful report. The chain is
    driver → device visibility → toolkit → acceleration libs → framework-sees-it → version match
    ; each layer has a different fix. Surface each layer separately.
  • Don't work only from
    .plain
    files.
    Always cross-reference with
    test_scripts/
    — the scripts are the executable contract. If a script invokes a non-language binary the specs never mention, that binary is automatically a Category 3 requirement.
  • Don't pre-bake a catalog. Derive the requirement list at runtime from the project in front of you. A hard-coded "things to always check" table becomes wrong the moment any project deviates from the assumed shape — and every project does.
  • Don't probe testing framework binaries as if they were independent.
    pytest
    ,
    jest
    ,
    vitest
    ,
    phpunit
    ,
    junit-console
    , etc. are installed by the package manager via
    requirements.txt
    /
    package.json
    /
    pom.xml
    . The toolchain check (Category 1) is enough — the framework binary itself is out of scope.
  • Don't probe in silence. Use the
    terminal
    tool and capture the actual command output (version strings, exit codes). Telling the user "looks like Python is installed" without running
    python3 --version
    is guessing.
  • Don't print secret values. Check whether
    CODEPLAIN_API_KEY
    ,
    DATABASE_URL
    , etc. are set, not what they contain. Use
    printenv VAR >/dev/null
    not
    printenv VAR
    .
  • Don't install anything on the user's behalf. Even when the install command is obvious. The user needs to opt in.
  • Don't stop at the first FAIL. Run the full sweep so the report is complete in one pass.
  • Don't suggest
    curl | sh
    installs when a package manager works.
    Reserve the upstream installer fallback for cases where no package-manager option exists (e.g.
    rustup
    , sometimes Go).
  • Don't ignore version mismatches. If a spec says Java 17 and the host has Java 21, surface that as a
    WARN
    so the user can decide — don't silently let it pass.
  • Don't duplicate this check inline elsewhere. Other skills (
    forge-plain
    ,
    add-feature
    ,
    plain-healthcheck
    ) that need an env check should delegate to
    check-plain-env
    rather than re-implementing the probe themselves. This skill is the single source of truth.
  • (严重错误)请勿探测单个语言包。任何可通过
    pip install -r requirements.txt
    npm ci
    mvn install
    cargo fetch
    go mod download
    bundle install
    composer install
    等命令解决的依赖均不在检查范围内。
    torch
    requests
    numpy
    FastAPI
    express
    react
    、JAR包、gem、crate等均属于包管理器的处理范围。仅检查工具链(
    python3
    pip
    node
    npm
    mvn
    cargo
    等)即可,无需进一步探测。探测包本身会在
    requirements.txt
    变更时产生误报,且重复了测试脚本会执行的工作。
  • 请勿仅检查直接提及的技术。规格中提到“使用PyTorch在本地硬件上微调”时,绝不会提到“CUDA”,但工作流程无法在没有CUDA的情况下运行。请始终检查类别3(语言包封装的系统二进制文件)和类别4(硬件/驱动程序)——不仅是直接提及的运行时。这些类别中包含工作流程的隐性需求。
  • 请勿将链式故障合并为单一的通用消息。“GPU不可用”并非有用的报告。故障链是
    驱动程序→设备可见性→工具包→加速库→框架识别→版本匹配
    ;每一层的修复方法都不同。请单独呈现每一层的结果。
  • 请勿仅依赖
    .plain
    文件
    。始终与
    test_scripts/
    进行交叉核对——脚本是可执行的契约。如果脚本调用了规格中从未提及的非语言二进制文件,该二进制文件自动属于类别3的需求。
  • 请勿预先内置固定清单。针对当前项目实时推导需求列表。硬编码的“始终需要检查的内容”表会在任何项目偏离假设形态时失效——而每个项目都会有所不同。
  • 请勿将测试框架二进制文件视为独立组件进行探测
    pytest
    jest
    vitest
    phpunit
    junit-console
    等均由包管理器通过
    requirements.txt
    /
    package.json
    /
    pom.xml
    安装。类别1的工具链检查已足够——框架二进制文件本身不在检查范围内。
  • 请勿静默探测。使用
    terminal
    工具并捕获实际的命令输出(版本字符串、退出码)。不执行
    python3 --version
    就告知用户“看起来Python已安装”属于猜测行为。
  • 请勿打印敏感值。仅检查
    CODEPLAIN_API_KEY
    DATABASE_URL
    等是否已设置,不要输出其具体内容。使用
    printenv VAR >/dev/null
    而非
    printenv VAR
  • 请勿代表用户安装任何内容。即使安装命令很明确,也需由用户自行选择是否执行。
  • 请勿在检测到第一个FAIL时停止。执行完整的探测流程,以便用户一次性获取完整的报告。
  • 请勿在包管理器可用时建议使用
    curl | sh
    安装
    。仅在没有包管理器选项时使用上游安装程序作为 fallback(例如
    rustup
    ,有时是Go)。
  • 请勿忽略版本不匹配。如果规格要求Java 17而主机安装了Java 21,请将其标记为
    WARN
    以便用户自行决定——不要静默通过。
  • 请勿在其他地方重复此检查逻辑。其他需要环境检查的技能(
    forge-plain
    add-feature
    plain-healthcheck
    )应委托给
    check-plain-env
    ,而非自行重新实现探测逻辑。该技能是环境检查的唯一可信来源。

Validation Checklist

验证清单

  • Host OS detected (
    uname -s
    /
    $OS
    ) before any other action.
  • Requirement list derived at runtime from this project's
    .plain
    files,
    test_scripts/
    ,
    config.yaml
    (s), and
    resources/
    — no pre-baked catalog used.
  • No individual language packages probed. Only the toolchain + package manager for each detected language.
  • Every script under
    test_scripts/
    opened and read; every non-language binary it invokes added to the Category 3 list.
  • Every external service named in the specs is in the Category 2 list, with both a binary probe and (when feasible) a reachability probe.
  • Every hardware / accelerator signal ("GPU", "fine-tune", "local inference", "CUDA", "MPS", etc.) triggered the layered Category 4 probe.
  • Every requirement probed via the
    terminal
    tool with an actual version / availability command (no "looks installed" guesses).
  • GPU / accelerator chains probed layer-by-layer (driver → device visibility → toolkit → acceleration libs → framework-sees-it → version match), with each layer reported separately.
  • Each result classified as PASS / WARN / FAIL.
  • Report has the verdict on the first line.
  • Every FAIL and WARN row has all four columns: What / Why / Status / How to install.
  • Install suggestions match the detected host OS (no Debian commands on macOS, no
    brew
    on Linux, etc.).
  • No secret values were printed at any point.
  • Nothing was installed; no project files were modified.
  • 在执行任何其他操作之前已检测主机操作系统(
    uname -s
    /
    $OS
    )。
  • 需求列表是从当前项目的
    .plain
    文件、
    test_scripts/
    config.yaml
    文件和
    resources/
    目录实时推导
    的——未使用预先内置的清单。
  • 未探测单个语言包。仅针对每个检测到的语言检查工具链+包管理器。
  • 已打开并读取
    test_scripts/
    下的所有脚本;脚本调用的所有非语言二进制文件已添加到类别3的列表中。
  • 规格中提到的每个外部服务已添加到类别2的列表中,同时进行二进制文件探测和(可行时)可达性探测。
  • 每个硬件/加速器信号(“GPU”、“微调”、“本地推理”、“CUDA”、“MPS”等)已触发类别4的分层探测。
  • 每个需求均通过
    terminal
    工具执行实际的版本/可用性命令进行探测(无“看起来已安装”的猜测)。
  • GPU/加速器故障链已逐层探测(驱动程序→设备可见性→工具包→加速库→框架识别→版本匹配),每一层的结果均单独报告。
  • 每个结果已分类为PASS/WARN/FAIL。
  • 报告第一行显示最终结论。
  • 每个FAIL和WARN条目均包含所有四列:检查项/原因/状态/安装方法。
  • 安装建议与检测到的主机操作系统匹配(macOS上不显示Debian命令,Linux上不显示
    brew
    命令等)。
  • 未打印任何敏感值。
  • 未安装任何组件;未修改任何项目文件。",