同一支程式,三種看法——程式碼、流程圖、積木。改哪一邊都算數,並且即時同步!
把真的 C++ 或 Python 貼進去,它變成積木;拖一塊積木,程式碼跟著變; 切到流程圖,它畫的是同一支程式。
🔴 三邊都是入口,不是「一個能改 + 兩個唯讀」:
你改程式碼 → 積木與流程當場跟著變
你改積木 → 程式碼與流程當場跟著變
你改流程 → 程式碼與積木當場跟著變
不是按一顆「轉換」按鈕,也不是存檔才更新——打字的當下另外兩邊就在動。
打一段 C++ → 三邊同時長出來 → 在程式碼、在積木、在流程各改一次,另外兩邊當場跟著變 → 按執行,它真的會跑
多數積木工具是單向的:積木能變成程式碼,而程式碼變不回積木。 少數做到雙向的(例如 MakeCode),走出它支援的子集就回不去。
Semorphe 想做的是另一件事:
| 三個畫面都能編輯,而且即時 | 程式碼、流程圖、積木任何一邊改,另外兩邊當場跟上——不是按一顆「轉換」,也不是存檔才更新 |
| 吃的是真的程式碼 | 貼一段你手邊的 .cpp 或 .py 進去,不是玩具子集 |
| 接不住的時候它會說 | 認不出來的語法不會被丟掉,也不會被猜——它變成一顆灰色積木,原文一字不動地放在裡面 |
第三點聽起來不像賣點,而它是:它保證這個工具不會安靜地弄壞你的檔案。
認不出來的 goto 變成一顆寫著原文的積木 → 在別的地方改一個數字 → 它一個字都沒動
這是 Arduino IDE 2.3.8 本人。左邊是它自己的編輯器,中間與右邊是
它的編輯器分頁——同一個 .ino 檔,三邊即時同步
Arduino + 積木的工具幾乎都住在 Arduino IDE 外面:
| 形狀 | 例子 |
|---|---|
| 另一個網站 | Tinkercad Circuits · Wokwi · Ardublockly |
| 另一個桌面程式 | mBlock · S4A(Scratch for Arduino) |
| IDE 的工具外掛 | ArduBlock(Arduino IDE 1.x,而它開的仍是一個獨立視窗) |
共同點是同一件事:積木不在你正在用的那個編輯器裡。於是流程長這樣——
在那邊拼 → 匯出 .ino → 切回 Arduino IDE → 燒錄。而那個「→」每一個都要錢:
兩個程式、兩份檔案 改了哪一邊要自己記,而記錯了沒有人會說
燒錄要換視窗 學生的注意力每次都要搬一次家
函式庫/開發板/序列埠 Arduino IDE 裡有的,外面那個要自己再做一份(而且永遠落後)
教的環境 ≠ 用的環境 學生「畢業」的那天要重學一次工具
Semorphe 是 Arduino IDE 的延伸模組,所以上面那四行都不存在:
| 同一個程式 | 裝上去就好,不用開第二個視窗、不用註冊帳號 |
| 同一個檔 | 那是 IDE 開著的 sketch_sep3a.ino——不是匯出的一份拷貝 |
| IDE 的原生分頁 | 積木與流程是編輯器分頁(拖到哪一欄都行),主控台與變數在 panel 那一排,與序列埠監控並排 |
| 三邊都能改 | 改積木 → .ino 當場變;改 .ino → 積木與流程當場變 |
| 編譯與燒錄照舊 | 左上角那兩顆 ✓ → 還是 Arduino 自己的——我們沒有接管它,也不想:函式庫、開發板管理員、序列埠都留在原地 |
| 同一份延伸模組 | VSCode 與 Arduino IDE 共用(Arduino IDE 2.x 是 Theia,吃 VSCode 的延伸模組) |
同步中(vscode-code-view) 是真的——文字那一側的真相是 IDE 的文件,
我們只送範圍編輯回去,所以你的檔案不會被我們整份覆蓋(見〈IDE 延伸模組〉)。
我們沒有找到第二個「積木活在官方 IDE 裡、對使用者自己的檔、而且雙向」的工具。 如果你知道有,請開一個 issue 告訴我們——那會是一個很有用的比較。
同一個網址(https://semorphe.com/)在手機上是專為觸控排的版面,不是把桌機 畫面縮小:
| 四個分頁 | 程式碼 · 流程 · 積木 · 主控台——一次專心一件事 |
| 拇指按得到 | 選單從下面升起來(頂端置中的清單,單手拿著手機按不到) |
| 不用安裝、不用帳號 | 開瀏覽器就是全部。 |
| 真的能執行 | 程式在你的裝置上跑,不是送到某個伺服器 |
🔴 這件事對誰重要:一間沒有電腦教室的學校、一個只有家長手機的孩子、 一節在走廊上的補課。程式教育的門檻常常不是能力,是那台機器。
而它不是「手機版的閹割功能表」:三邊同步、執行、課程、鷹架, 在手機上是同一套東西——因為它們本來就是同一份程式碼。
- 由淺入深 — 66 堂課、6 條軌道(C++ 入門/進階、C 銜接、Python 入門/銜接、Arduino 專題)。 工具箱只給這一堂該有的積木
- 骨架看得到、拆不壞 —
#include、int main()這些「不是你寫的」那幾行, 可以藏起來、可以淡淡地顯示(看得到而拖不動)、也可以整個交給學生 - 多種程式碼風格 — APCS(
cout/cin)、競賽(printf/scanf)、Google、Python 一鍵切換 - 硬體 — 8 塊板子(Uno/Nano/ESP32 家族/D1 mini…), 每塊板子有自己的腳位、常數與函式庫標頭
- 離線可用 — 跑起來之後不會向外要任何東西(有一條測試守著)
- IDE 延伸模組 — VSCode 與 Arduino IDE 共用同一份
66 堂課的課文是靜態頁——純 HTML、不載編輯器、打開就在那裡
(semorphe.com/lessons/)。每一頁底下有一顆「在編輯器打開這一課」,
而編輯器裡的章節選單有一顆「📖 看這一課的課文」——兩邊互相指得回去。
課文 → 「在編輯器打開這一課」 → 工具箱只剩這一課要的、鷹架是淡的 → 照著打,積木長出來
| 課文 | 每一課一頁,/lessons/<軌道>/<課>/——有上一課/下一課,不跨軌道 |
| 一堂課會做什麼 | 釘住目標(語言/板子)、收窄工具箱到這一課的元件、決定鷹架露多少 |
| 一條連結就夠 | ?lesson=<軌道>/<課> — 老師貼出去,學生點開就是那一課的環境 |
那 66 堂課的課文早就寫好了(13 萬字),而在 2026-09-03 之前 產品裡沒有任何讀者——唯二讀它的是兩支測試,而它們讀完就丟。
三個投影各佔一欄,而哪一格顯示哪一層由你決定:
| 三張版面 | 專注(一次一個)/對照(程式碼 + 積木)/三欄 |
| 每一格自己選 | 每一格的頭上有一顆下拉「這一格顯示」——選到別處的就對調 |
| 主控台在底下 | 它不是投影,是執行的輸出——所以它是編輯區底下一條獨立、全寬、關得掉的底條(主控台/變數兩頁) |
關掉主控台 → 按執行,它自己回來 → 用「這一格顯示」把兩格對調 → 切「對照」收成兩欄
主控台關得掉,而它一定回得來:版面選單叫得回來,而程式一有輸出它自己就回來。
寫在這裡,因為你遲早會撞到:
- 語言只有 C++(含 C 方言)與 Python。加一個語言是一整刀,不是設定
- 認不出來的語法會降級成灰色積木。它跑得動、來回轉換不會壞,但它在積木上就是一塊灰的
- Arduino IDE 沒有自動更新——它把擴充市集對使用者關掉了,只能手動放
.vsix(步驟見安裝,⚠️ 更新時有一個少了會安靜失敗的步驟) - 流程圖是新的(2026-08),它的編輯能力還在長
- Arduino IDE 排不出等寬的三欄——它沒有那顆指令(查證過),要手動拖分隔線
不想裝的話,網頁版就是完整的同一套東西—— 以下只在你想「在自己的編輯器裡用」時才需要。
方法一:市集(會自動更新)
擴充商店搜 Semorphe,或直接開 市集頁面。
方法二:.vsix 檔
到 Releases 下載
semorphe-vscode-<版本>.vsix,然後任選一種:
code --install-extension semorphe-vscode-0.16.0.vsix或在 VSCode 裡:命令面板(Cmd/Ctrl + Shift + P)→
Extensions: Install from VSIX… → 選那個檔。
🔴 Arduino IDE 沒有安裝擴充的介面——它是 Theia 做的,而它把擴充市集 對使用者關掉了。所以只能把檔案放進去:
-
到 Releases 下載
semorphe-vscode-<版本>.vsix -
完全關掉 Arduino IDE
-
把檔案放進這個資料夾(不存在就自己建):
macOS / Linux ~/.arduinoIDE/plugins/Windows %USERPROFILE%\.arduinoIDE\plugins\ -
重開 Arduino IDE——它會自己解壓——命令面板 → Semorphe: 開啟積木面板
更新:一樣的四步,而第 3 步先把舊的 semorphe-vscode-*.vsix 刪掉。
檔名帶版本是有意的:Theia 的解壓快取以名字為鍵,版本進到名字裡,
新舊就不會混。
🪦 這不是官方支援的安裝方式,Arduino IDE 換一版就可能失效。 如果哪天它不動了,網頁版是同一套東西。
兩個宿主一模一樣(Arduino IDE 是 Theia,吃同一份擴充),只有介面位置略有不同。
.ino · .cpp · .c · .h · .py——新檔案也行,把語言選成 C++ 或 Python 就會出現。
| 怎麼叫 | 做什麼 |
|---|---|
編輯器右上角的 <Σ> 圖示 |
開積木—— |
命令面板(Cmd/Ctrl+Shift+P)→ Semorphe: 開啟積木面板 |
同上 |
| 命令面板 → Semorphe: 開啟流程面板 | 開流程圖 |
它們是編輯器分頁——拖到右邊、拖到下面、拖到另一個視窗都可以, 就跟你平常拖任何一個分頁一樣。
它們在 panel 那一排(與終端機/問題/輸出並排),叫做 Semorphe 主控台與 Semorphe 變數。
| VSCode | 檢視 → 開啟檢視… → 搜 Semorphe;或命令面板 → Semorphe: 主控台 |
| Arduino IDE | 它們直接在最上面那條功能表列上 |
| 在哪 | 有什麼 |
|---|---|
| 狀態列(右下) | 目標(語言/板子)· 課程 · 章節 · 鷹架 · 風格 · 積木外觀 · 介面語言 · 版面 |
| 標題列(分頁右上) | ▷ 執行 · ↩ 還原 · ↪ 重做 |
| 每一格的右上 | 「這一格顯示哪一層」——選到別處的就對調 |
🔴 版面(專注/對照/三欄)是一句請求:分頁與分欄是 IDE 自己的東西, 我們只能請它把某一格放到第幾欄——所以三個宿主的版面清單逐字相同。
命令面板 → Semorphe: 顯示同步診斷——它會印出寫入歷程、鏡像對帳、宿主能力。 回報問題時把那一段貼上來,比任何描述都有用。
npm install
npm run dev # 開發伺服器
npm test # 單元/整合測試
npm run test:e2e # Playwright
npm run build # tsc + vite build
npm run build:vscode # 打包 IDE 延伸模組
npm run install:ide # 裝進本機的 VSCode / Arduino IDEsrc/
├── core/ # 語義樹本身、兩個方向的轉換引擎、各語言登記自己資料的地方
├── components/ # 一顆「程式概念」一個資料夾(if、迴圈、印出來…)
├── languages/ # 每個語言一包:解析器、課程、目標板子、程式碼風格、工具箱分類
├── interpreter/ # 語義樹直譯器
├── ui/ # 三個面板(積木 / 流程圖 / 程式碼)與它們之間的同步
└── vscode/ # IDE 延伸模組(VSCode + Arduino IDE 共用)
程式碼 ──讀進來──→ 語義樹 ──寫回去──→ 程式碼
│
├──→ 積木
└──→ 流程圖
中間那棵樹是唯一的真相。 三個畫面都從它算出來,也都改得動它, 而沒有任何一條捷徑——不會有「積木直接翻成程式碼」這種路。
那正是多數同類工具會漂掉的地方:兩邊各自維護一份翻譯, 改了一邊而另一邊沒跟上,久了就對不起來。
專案裡把那三個畫面叫做投影——一個投影是從真相算出來的, 所以它可以少(積木上看不到
#include),但不會多出真相裡沒有的東西。兩句標語:「唯一真實,各式投影。」 教育情境的那句是「解構語法之散,重塑形態之模」。
一個程式概念(if、while、印出來、變數指派…)= 一個資料夾。
專案裡叫它膠囊,因為它把那個概念的每一面都裝在同一處:
src/components/python/loop_while/ ← Python 的 while 迴圈
component.json 它叫什麼、有哪些欄位、可以接哪些子積木
lift-pattern.json 怎麼從【程式碼】認出它
generate.ts 怎麼把它寫回【程式碼】
forms/blocks.json 它畫成【積木】長什麼樣(同一份也用來從積木讀回資料)
execute.ts 執行它會發生什麼事
labels/zh-TW.json 積木上的中文字(另有 en.json)
spec.test.ts 它自己的測試
那五件事(認出來 · 寫回去 · 畫出來 · 讀回來 · 執行)就是一顆元件的全部——
少任何一件都要在 component.json 裡寫明為什麼沒有,
好讓「刻意不做」與「忘了做」分得出來。
🟢 加一顆元件=新增一個資料夾。 系統自己會掃到它, 不需要去別的檔案登記——所以加東西不會弄壞既有的東西。
Semorphe 把重複的開發流程寫成 skill——給 AI 助理看的操作手冊
(原始檔在 knowledge/skills/,用符號連結出現在 .claude/skills/)。
它們不是模板,是這個專案的記憶:裡面幾乎每一條規矩後面都有一次具體的翻車, 而那次翻車就寫在旁邊。
/component-pipeline {lang} {target}
它串起六個階段:
| 階段 | Skill | 做什麼 |
|---|---|---|
| 1 | component-discover |
查這個函式庫/語法有哪些概念,該怎麼命名、放在第幾關 |
| 2 | component-generate |
產出上面那個資料夾裡的每一個檔 |
| 3 | component-roundtrip |
程式碼 → 積木 → 再變回程式碼,跑起來比對輸出 |
| 4 | component-fuzz |
出題的 AI 看不到實作,只有這樣它才會問你不會問自己的問題 |
| 5 | component-integrate |
最終關卡:型別檢查、全套測試、來回轉換全部通過才算數 |
| 6 | verify-in-browser |
🔴 打開瀏覽器【用眼睛看】——前五關全綠而使用者一看就發現的缺陷 |
/add-language
從零加一個語言要處理的是另一批東西:接上解析器、
讓系統知道每條辨識規則是寫給哪個語法的(少了這一步,
新語言的 if 會被當成舊語言的 if,而且不會有任何錯誤訊息)、
以及四件「這個語言怎麼寫註解」「認不出來時用哪顆灰色積木」之類的登記。
| Skill | 用途 |
|---|---|
component-refactor |
檢查與修復既有的元件(它讀的是自動檢查產生的報表,不是自己重掃) |
component-rename |
大規模改名(上千處引用)——一定要附使用者舊存檔的轉換 |
build-guardrail |
把一條「應該要這樣」的規矩,變成一支做錯就會變紅的測試 |
manual-acceptance |
有些規矩測不起來(「按下去看到什麼」)——寫成一張人按得完的清單 |
diagnose-in-browser |
已經知道有問題時,在瀏覽器裡查出是哪一段 |
ship-extension |
把一次改動交到兩個 IDE 手上(這條流程跑了九次才被固定下來) |
完整清單與各自的緣起見 knowledge/skills/README.md。
已出貨,VSCode 與 Arduino IDE(Theia 1.57)共用同一份 .vsix。
(畫面見上面〈積木長在 Arduino IDE 裡面〉。)
面板【就是】網頁版的 App,只是程式碼那一格換成宿主的編輯器
而 2026-09 之後它長成宿主原生的形狀:
| 這一層 | 住在哪 |
|---|---|
| 程式碼 | IDE 自己的編輯器 |
| 積木 · 流程 | 各自一個編輯器分頁(semorphe.openBlocks / openFlow) |
| 主控台 · 變數 | panel 區的兩個原生分頁,與終端機/問題並排 |
| 控制項 | 狀態列(目標、課程、風格、版面…)+ 標題列(▷ 執行、↩↪) |
三個宿主(網頁、VSCode、Arduino IDE)的版面清單逐字相同,因為三張版面 全是純欄——排它只需要「把這一格放到第幾欄」,而那是每個宿主都做得到的 最小動作。
🔴 上一版有一張「十字」(四格,主控台佔一格),而它是唯一需要編輯區有 第二列的版面——Theia 沒有
setEditorLayout,那一格排不出來。 拿掉它之後,三個宿主第一次是同一個形狀。 見history/202。
都是量出來的(bundle 裡查證 + 實測),而不是猜的:
| VSCode | Arduino IDE | |
|---|---|---|
| 三欄等寬 | ✅ 自動 | ❌ 它沒有「平均欄寬」那顆指令——要手動拖 |
| 「這一格改顯示程式碼」 | ✅ | ❌ 不列入選單(它關不掉多開的那個檔案分頁) |
| 面板現在開著沒有 | ✅ 答得出 | ❌ 答不出 → 選單改用中性的名字(不假裝知道) |
名單住在 src/vscode/host-quirks.ts,每一筆都附病歷,而且都有「實測會降級」
的第二層——
npm run build:vscode # 產出 .vsix
npm run install:ide # 裝進本機兩個 IDE.vsix——install:ide 會處理兩邊的快取失效
(Theia 以資料夾名字為鍵、VSCode 以 (id, version) 為鍵,兩個都是
「換了而不重載,且不報錯」)。使用者的手動步驟見安裝。
🪦 2026-03 的那個原型已於 2026-08-16 退休(教訓見
knowledge/history/069), 現在這一份是 2026-08 重做的。
這個 repo 把「為什麼」寫下來了,而且它是權威的,不是裝飾。動手之前依序讀:
CLAUDE.md— 什麼時候跑什麼測試(⚠️ 那張表有一列是紅字的,別跳過)knowledge/principles.md— 不可協商的那幾條knowledge/vision.md— 下一步在哪knowledge/experience.md— 前人踩過的坑(找與你這一刀相關的)
三件會讓一次改動被擋下來的事:
- 改了規範而沒有機械化的檢查 — 見
knowledge/skills/build-guardrail。 這個專案有 113 條護欄(數字由tests/integration/audit-guardrail-count.test.ts算出來,而它會擋住這一行變成過期的數字),而它們的存在理由是同一句: 一條規範沒有機械化的檢查,它本身就是殼——而殼看起來像完成。 - 改了使用者按得到的東西而沒跑
npm run test:e2e— 全套單元測試綠擋不住它 - 把同一個決定實作第二次 — 這裡發生過六次,見
history/188
knowledge/skills/ 裡有 19 支學過的流程(加語言、生課程、退場一顆積木…)。
你要做的事如果在裡面,照著走,不要重想——每一條規矩後面都有一次具體的翻車。
這個專案的 why 記在 knowledge/,而不是散在 commit 訊息裡:
principles.md |
根公理與衍生原則——不可協商的那些 |
vision.md |
定位與還活著的路線圖(完成的收斂成一行 + 指標) |
experience.md |
從翻車裡蒸餾出來的教訓 |
concepts/ |
反覆出現的概念,各自一篇 |
history/ |
「為什麼變成現在這樣」的因果紀錄——每次改變都留一筆 |
episodes/ |
值得重看的完整除錯現場 |
draft/ |
還沒定案的想法(沒有被用到就會自然淡掉) |
MIT




