- name
- easyeda-eprj3
- description
- Build EasyEDA Pro / 嘉立创EDA专业版 .eprj3 projects (schematic + PCB) from one design.json — offline schematic layout + wiring, PCB placement, four gates, plus a 2.x CLI bridge (client V4.1.94+) for library search, PCB auto layout/route, copper pour + fill, netlist export/compare and screenshots. Use whenever the user wants to create or edit an eprj3 project, generate symbols/footprints, or validate/repair one.
# EasyEDA Pro eprj3 Skill
Author **EasyEDA Pro** (嘉立创EDA专业版) folder-format `.eprj3` projects. One design
file in, one validated project out: schematic laid out in signal-flow blocks,
every net wired, **PCB placed** — then four independent gates.
**Strategy: the skill places, the client finishes the copper.** 2.x drives the
desktop client through its CLI for everything the client does best (library
search, auto layout/route, pour, netlist extraction, screenshots). The skill
itself still **never implements a router or a pour engine** — it prepares the
project and the scripts, then lets the client execute. Without the client the
offline pipeline still produces a placement-only board and prints a **rats
handoff list**; `D004` (unrouted) and `D006` (missing pour) are never judged on
a board this skill built.
Format ground truth: [`docs/format-reference.md`](docs/format-reference.md). Deep
details are load-on-demand — see [Where to read next](#where-to-read-next) instead
of reading everything up front.
## 运行时任务进度
动手前先打印任务清单,让用户一眼看到「共几项、现在做哪项」;每完成一项立即更新,
不要闷头跑完才汇报。
标准流程共 5 个关键任务:
```
- [ ] 0. 环境检查 doctor(用到 2.x CLI 功能时必做:客户端 4.1.94+)
- [ ] 1. 需求采集 intake(设计文件已给出则跳过)
- [ ] 2. 生成工程 build(含门禁;客户端建板时 PCB 由原理图导入,离线建板再跑 netcheck)
- [ ] 3. 网表审计 audit(全新子 agent 复核;2.x 可用 eda.js netlist 导出)
- [ ] 4. 报告 report(project-report.md + ai-report.md)
- [ ] 5. 打开客户端 open(完成后默认打开,便于查看;生成过程本身全程无头,不弹窗)
```
**Headless while generating, GUI at the end.** Every client interaction during
generation (symbol placement, schematic → PCB import, auto layout, DRC) runs in
a headless session and the bridge is booted in `serve-hidden` mode — generating
a project never opens the client window. Only the final `node scripts/open.js`
shows the GUI, which is the intended last step.
运行时约定:
- 开场打印清单,并写一句 `开始:共 N 项任务`(N 按实际执行项计,跳过的步骤先划掉)。
- 每完成一项把该项勾上,再打印 `✅ [i/N] <任务名> 完成`。
- 全部完成后打印汇总:`✅ 完成 N/N —— <一句话结果>`。
- 失败即停在当前项:打印 `❌ [i/N] <任务名> 失败` 和原因,报给用户后不要静默继续。
## Step 0 — intake: ask once, then never again
When the request is a *feature* ("做一个温湿度采集板") rather than a design file,
run the intake protocol before writing anything:
```bash
node scripts/intake.js check --req req.json # exit 1 = required fields missing
node scripts/intake.js resolve --req req.json --out design.json
node scripts/build.js --design design.json --dir <proj> --plan # confirm gate
node scripts/build.js --design design.json --dir <proj> # after the user says ok
```
- `check` prints the exact questions (zh) for missing fields — send them **all at
once**, never serially. Ask-tier fields carry their fallback default.
- `resolve` maps keywords to recipes (`usb`→usb-c-power, `3V3`→ldo-3v3,
`单片机/mcu`→mcu-min+crystal…), chains the power tree
(12V→buck→5V→ldo→3V3) and derives rail widths from the declared current.
Selections are cached (`.cache/`) — a repeated requirement resolves in one
lookup.
- **Confirmation gates before you build or fix:** power scheme, MCU/critical part
choice, interface names, layer count (the board outline is auto-sized),
**PCB layout engine**, and `autofix.js --diff` output (a diff summary before
any automatic edit). Ask the layout question explicitly:
- **new project** — "PCB 布局用 AI 生成的坐标(skill 规划,可精确约束)还是
EDA 客户端自动布局?" → `--layout skill` / `--layout client`;
- **existing project** — "保留已有布局,还是重新布局?" keep →
`--keep-layout`; re-layout → `--layout client`, then ask "允许移动锁定的
元件吗?" yes → `--move-locked`, no → omit it (locks stay).
Full protocol + field table: [`docs/intake.md`](docs/intake.md).
If the user supplied a complete design already, skip to the fast path.
## Fast path (use this unless the user asks otherwise)
```bash
# 1. write a design file (see below), then:
node scripts/build.js --design design.json --dir <absolute project dir>
# ... builds schematic + PCB PLACEMENT, runs validate + ERC + lint + DRC
# the PCB is placement-only; the run prints the rats list of nets to
# connect by hand in the EasyEDA client (this skill never routes or pours)
# placement: one cluster per schematic block (caps beside the pads they
# decouple), connectors (J/CN/USB) on the board edge, board auto-sized
# to 1.25× the footprint bbox area (a declared size is ignored; a tiny
# board may be slightly larger because the edge clearance sets a floor)
# client builds (any "ic" part): after the board outline + import the
# build runs the client's PCB auto layout (pcb_Document.autoLayout) and
# keeps that result. ASK FIRST (new project): AI coordinates or EDA auto
# layout? → --layout skill | client; explicit pcb.place parts are locked
# during the EDA pass (--move-locked lets it move them). Rebuilding an
# existing project: keep layout → --keep-layout, re-layout → --layout client
node scripts/netlist.js --dir <project dir> --design design.json --audit <project dir>/.tmp/netlist-audit.json
# netlist audit package → a FRESH sub-agent reviews it (mandatory; see the
# "Netlist audit" section below, not an optional nicety)
node scripts/netcheck.js --dir <project dir> # schematic ↔ PCB netlist diff (build runs it on every PCB, client-imported included)
node scripts/report.js --dir <project dir> --design design.json --report <dir>/build.json
# project-report.md (概述/功能描述/功能特性/BOM/信号框架图/电源框架图/网络/门禁/遗留/建议)
# then write ai-report.md yourself — every agent's tokens + times with
# totals, see "Reports" below
node scripts/make-board.js --design design.json --dir <dir> --force # one-shot: build → digest + audit package + project-report.md
node scripts/floorplan.js --design design.json # preview the PCB placement map (no build; --write pins it into pcb.place)
node scripts/open.js open --dir <project dir> # final step: open the .eprj3 in the client GUI (generation itself is headless)
```
## 2.x — CLI-first workspace (client V4.1.94+)
2.x hands the work the desktop client does best to the client, through its
command line. **Check the environment first** — every 2.x script refuses to run
on an older client:
```bash
node scripts/eda.js doctor # version / endpoint; non-zero below 4.1.94
```
Then call a script instead of hand-writing JavaScript:
| Need | Script | Client API |
| --- | --- | --- |
| find a device (keyword / LCSC) | `eda.js search --q …` / `--lcsc …` | `lib_Device.search` / `searchByProperties` |
| official pin table | `eda.js pins --lcsc …` / `--q …` / `--device …` | `lib_Symbol.getGeometry` |
| netlist for review | `eda.js netlist --dir <p> --out review/netlist.json` | `sch_ManufactureData.getNetlistFile` |
| schematic DRC | `eda.js sch-drc --dir <p>` | `sch_Drc.check` |
| visual check | `eda.js screenshot --dir <p> --out shots` | `getPngFile` / `getCurrentRenderedAreaImage` |
| PCB layout engine | `build.js --layout skill|client` (`pcb.layout`) | skill planner vs `pcb_Document.autoLayout` |
| PCB auto layout/route | `eda.js pcb --layout/--route [--move-locked]` | `pcb_Document` |
| — | **build.js runs `pcb --layout` automatically on client builds** (after the board outline and the schematic→PCB import) when the user chose the EDA layout; explicit `pcb.place` parts are locked for that pass unless `--move-locked` | `pcb_Document.autoLayout` |
| copper pour + fill | `eda.js pour --net GND --outline x1,y1,x2,y2` (data units = mil) | `pcb_PrimitivePour.create` + `rebuildCopperRegion` |
Rules:
- **Source APIs first — for the work the client owns.** When the skill drives
the client it uses the `sch_Source*` family (project-source edits with no open
page, the fastest route; e.g. `sch_SourcePrimitiveComponent.add`,
`sch_SourcePrimitiveWire.add`). Document APIs are only for auto layout / auto
route / rendering, which need an open document. On client builds the routed
wires are drawn through `sch_SourcePrimitiveWire.add` and power/ground flags
through `sch_SourcePrimitiveComponent.addNetFlag`; the offline record emitter
remains for no-client builds, zero-length anchor wires (the API rejects those,
and the PCB import needs them) and net ports (`netport-*` via `add` gets a
designator and a different orientation).
- **Scripts, not snippets.** The model runs these scripts; it does not write
editor JS itself. A new capability means a new `eda.js` subcommand. Never
create ad-hoc dump/explore scripts in the project (e.g. `tmp/dump-pins.js`)
that `require` the skill's `scripts/lib/*` — official pin tables come from
`eda.js pins`, everything else from the shipped commands; report a missing
command instead of improvising one.
- **The client builds the PCB from the schematic.** When a build uses the
client, `build.js` places the official symbols, draws the routed wires
through `sch_SourcePrimitiveWire.add`, then calls
`pcb_Document.importChanges(schUuid, true)` and moves the imported footprints
to the planned positions. Footprints and pad nets come from the client's own
update, so the PCB netlist is complete by construction — no schematic ↔ PCB
comparison step. The offline `netcheck` gate still covers no-client builds.
- **Schematic DRC after drawing.** With the client, the build also runs
`sch_Drc.check(true, false, true)` on the finished sheet: the report is
`schDrc` in `build.json` (rule / net / designator / pin), fatal/error items
fail the build (`--allow-sch-drc` overrides), and `eda.js sch-drc` re-runs it
for the repair loop. Router vertices, flags, ports and net labels are snapped
to the 50-mil grid so NETOBJECTONGRID stays at zero.
- **Close sessions.** Every command opens a headless session and destroys it;
batch loops must not leak editor windows (`--keep` only for debugging).
- **Schematic layout and wiring always use the skill's own engine.** The
client's schematic auto engine ignores module frames and reads worse; do not
delegate schematic placement/routing to it. The client does PCB copper
(auto route / pour) and the review/screenshot/netlist work.
- Full flags, API mapping and limitations: [`docs/cli.md`](docs/cli.md).
## Netlist audit — a fresh reviewer, not you
A green build proves the files are well formed and every gate ran — including
`E003`, which compares the built netlist with design.json **inside the build**.
That is not an independent check: the agent that wrote design.json is the agent
reading the verdict, and a mistake shared by both sides (a wrong pin number in
the design, a net the layout silently merged) is invisible to it. So every
build gets one read of the netlist by a reviewer that has **none of your
context**:
```bash
node scripts/netlist.js --dir <project> --design design.json \
--audit <project>/.tmp/netlist-audit.json
# generator-authored board? --gen board.gen.js replaces --design (the same
# design the build used — there is no design.json to read)
```
`make-board.js` already writes this package to `<project>/.tmp/netlist-audit.json`
and lists it in the digest as `audit: {ok, file}` — hand that `file` straight to
the reviewer, no extra command.
**2.x variant — review the client's own netlist.** With the desktop client
openable (V4.1.94+), export the netlist the client itself computed and reduce it
to the fields the reviewer needs:
```bash
node scripts/eda.js netlist --dir <project> --out <project>/.tmp/netlist.json
```
`netlist.json` is `{ parts:[{ref,name,device,footprint,pins:{num:net}}],
nets:{name:[ref.pin]} }` — refdes, connections and model names only, no
geometry. Hand **that** file to the same fresh-subagent review (ask it to check
each net against the PRD and flag wrong pin numbers / missing parts / shorted
nets). The PCB side needs no separate check: the client builds it from this
same schematic. Use this path when the client is available; the package path
above stays the offline fallback.
The package is self-contained (schema `eprj3-netlist-audit/1`):
| Field | Meaning |
| --- | --- |
| `spec` | what the design asked for — every part's pin→net map, `powers`, `expect` |
| `built` | what the schematic actually connects — nets, pins, power-flag counts, unconnected pins, PCB pad nets |
| `mechanical` | the tool's own diff, `mechanical.ok`, netcheck verdict, plus advisory `suspicions` |
| `rubric` | the checklist the reviewer must perform |
| `verdictSchema` | the exact JSON the reviewer must return |
Hand the **file path** (absolute), never your notes or reasoning, to a **fresh**
sub-agent. Copy this task verbatim:
> You are an independent netlist auditor. You have no prior context and need none.
> Read `<absolute path to netlist-audit.json>`. It is a self-contained audit
> package (`schema: eprj3-netlist-audit/1`): `spec` is the required pin→net map
> from design.json, `built` is the netlist recovered from the generated
> schematic, `mechanical` is the tool's diff — **do not trust it**, recompute
> every net group from `spec.parts` and `built.nets` yourself — `rubric` lists
> the checks you must perform, `verdictSchema` is the required output shape.
> Follow the rubric, then output ONE JSON object and nothing else: no prose, no
> markdown fence. `ok` is true only when no finding has severity "error".
Then loop, **max 3 rounds**:
1. `mechanical.ok === false` — a hard floor that applies **even if the reviewer
said ok** — or the reviewer returns `ok: false` → apply each finding's `fix:`
to design.json (or to the gen/recipe that produced it), rebuild with
`--force`, regenerate the package, and spawn a **new** reviewer. If the
reviewer missed a mechanical failure, repair straight from
`mechanical.diff` / `missingPins` / `pinTwice`. Never follow up with the
previous reviewer: it has seen the old netlist and would be grading its own
earlier answer.
2. `ok: true` → go on with `netcheck`, `open`. Put the reviewer's `summary` in
your final report, so the user knows the netlist was independently read.
3. Still failing after 3 rounds → **stop** and show the findings to the user
verbatim. Do not accept them silently and do not loop forever.
A finding with no concrete `fix:` is not actionable — ask that reviewer for the
design.json line in the same round; never guess a repair. After a green audit,
`node scripts/cleanup.js --dir <project>` removes `.tmp/` (the audit package
lives there; a rebuild wipes it too).
If the host has no sub-agent capability, run `rubric` yourself against the
package — and say plainly in your report that the audit was **not independent**.
## Reports — project-report.md + ai-report.md
Every finished build ends with two human-readable reports next to the project:
- **`project-report.md`** — auto-generated by [`scripts/report.js`](scripts/report.js)
(`make-board.js` writes it for free): 工程概述 / 功能描述 / 功能特性 / 物料清单
(BOM)/ 信号框架图 / 电路(电源)框架图(mermaid)/ 网络概览 / 验证结果 /
遗留问题 / 建议. Every fact comes from design.json + the built project, never
invented; the judgement sections (一句话功能, 建议) are yours to top up.
The diagrams are distilled, not dumped: the signal graph shows one arrow per
module pair (net names merged), the power graph chains rails through their
converters (`12V → U1 → 5V → U1_ldo → 3V3`) and hangs each block under the
rail that feeds it.
- **`ai-report.md`** — written **by you**, because only the host knows the model,
token usage and wall-clock. It must account for **every agent that touched the
run** — the main agent plus each sub-agent instance (each audit round is its
own row) — and end with **totals across all agents**. Record timestamps as you
go (start at intake, then build → audit → report → open), and fill this
template at the end:
```markdown
# ai-report — <project name>
| 项 | 值 |
| --- | --- |
| 工程目录 | `<dir>` |
| 主 agent | easyeda-eprj3(本 skill) |
| 使用的模型 | `<model id / 名称,宿主提供>` |
| 子 agent 数 | `<N>`(每个审计轮次一个全新实例) |
| 开始时间 | `YYYY-MM-DD HH:MM:SS` |
| 结束时间 | `YYYY-MM-DD HH:MM:SS` |
| 总耗时(墙钟) | `<duration>` |
## Agent 用量明细(全部 agent)
| # | agent(角色) | 模型 | 开始 | 结束 | 耗时 | 输入 token | 输出 token | 总 token | 说明 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | 主 agent(intake → build → 报告) | | | | | | | | 墙钟见上表 |
| 2 | 网表审计 auditor #1(全新实例) | | | | | | | | 第 1 轮 |
Auf GitHub ansehen