Migrate Internal Package into Ghost
TryGhost/Ghost
Moves a package from another TryGhost repository into Ghost as an internal workspace package while keeping its Git history, with checkpoints for the steps that need an administrator.
Complete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format.
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ailyProject/aily-blockly library-migration-guide --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .claude/skills && cp -r skills-src/public/skills/library-migration-guide .claude/skills/library-migration-guide && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .claude/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guideType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ailyProject/aily-blockly library-migration-guide --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .agents/skills && cp -r skills-src/public/skills/library-migration-guide .agents/skills/library-migration-guide && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .agents/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ailyProject/aily-blockly library-migration-guide --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/public/skills/library-migration-guide .cursor/skills/library-migration-guide && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .cursor/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/ailyProject/aily-blockly.git --path public/skills/library-migration-guide--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ailyProject/aily-blockly library-migration-guide --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/public/skills/library-migration-guide .gemini/skills/library-migration-guide && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .gemini/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ailyProject/aily-blockly library-migration-guideInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .github/skills && cp -r skills-src/public/skills/library-migration-guide .github/skills/library-migration-guide && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .github/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ailyProject/aily-blockly --skill library-migration-guide -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ailyProject/aily-blockly library-migration-guide --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ailyProject/aily-blockly.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/public/skills/library-migration-guide .opencode/skills/library-migration-guide && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "library-migration-guide" agent skill from https://github.com/ailyProject/aily-blockly/tree/main/public/skills/library-migration-guide into .opencode/skills/library-migration-guide/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "library-migration-guide", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
library-migration-guideComplete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format.
Library Migration Guide is an agent skill from ailyProject/aily-blockly. Complete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format. Covers the full workflow: source analysis, block.json design, generator.js implementation, toolbox.json configuration, bus initialization (Serial/I2C/SPI), board adaptation, and packaging.
Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `Blockly_Library_CODE_Conventions.md`).
It sits in Development, covering Embedded systems and Code migrations. It works with ESP32 and npm. The repository describes itself as: AI IDE for hardware development, support Arduino, MicroPython, ESP32, STM32, RP2040, Nrf5x... The licence is GPL-3.0.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 4aace5a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
blockly.diandeng.techFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Library Migration Guide loads about 3.1k tokens when it runs. Until then it costs about 78 tokens; SKILL.md has 836 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from ailyProject/aily-blockly at commit 4aace5a, republished under its GPL-3.0 licence (© ailyProject). 836 words, ~3,137 tokens.
.claude/skills/library-migration-guide/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.A systematic guide for converting Arduino libraries into Aily Blockly libraries, based on real conversion cases (ArduinoJson, OneButton, MQTT/PubSubClient, DHT, INA219, VL53L0X, etc.).
project with action="create" to create one, then continue with the new project path.All library files MUST be created in <projectPath>/<library-name>/, NOT in node_modules/.
<projectPath>/lib-grove_motor/block.json<projectPath>/node_modules/@aily-project/lib-grove_motor/block.jsonThe node_modules/ directory is managed by npm and is write-protected.
After creating the library locally, install it with: npm install ./<library-name>
If a file write operation returns a path/permission error, check your target path — you are likely
writing to node_modules/ instead of <projectPath>/<library-name>/. Fix the path and retry.
Do NOT attempt to bypass by using terminal commands (mkdir, echo, Out-File, etc.) to write into protected directories.
Source Analysis: Analyze the Arduino library header files to identify public APIs. Classify by operation type: initialization, connection, communication, status, maintenance, quick operations.
Block Design: Design user-friendly blocks following block type mapping rules (see Section "Block Design Rules" below).
Create Library Files in <projectPath>/<library-name>/:
block.json — Block definitionsgenerator.js — Code generatortoolbox.json — Toolbox configurationpackage.json — Library metadataCopy Source Files: Use run_terminal to copy the Arduino source:
src/ folder exists → copy to <projectPath>/<library-name>/src/<library-name>/src/ folder → copy .c, .cpp, .h, .hpp files to <projectPath>/<library-name>/src/<library-name>/Write README.md: First read Blockly_Library_README_Conventions.md (fetch from https://blockly.diandeng.tech/files/Blockly_Library_README_Conventions.md), then follow its format.
Post-conversion: Ask the user if they need help with:
npm i <library-path> (must specify the local library path)library-name/
├─ block.json // Block definitions
├─ generator.js // Code generator
├─ toolbox.json // Toolbox configuration
├─ package.json // Library metadata
├─ README.md // Human-readable documentation
├─ README_AI.md // LLM-readable documentation
└─ src/
└─ library-name/ // Copied Arduino source filesIMPORTANT: For complete code specification with detailed examples, read the companion file
Blockly_Library_CODE_Conventions.md located in this skill's folder. It covers:
The sections below summarize the critical rules that MUST be followed.
| Arduino Pattern | Block Type | Connection | Field Type |
|---|---|---|---|
| Object creation/init | Statement | prev/next | field_input (user enters new var name) |
| Global object method | Statement | prev/next | No variable field (direct call) |
| Object method call | Statement | prev/next | field_variable (select existing var) |
| Global object query | Value | output | No variable field |
| Quick operation | Statement/Value | standard | No variable field, direct params |
| Event callback | Hat block | No prev/next | field_variable + input_statement |
| Conditional callback | Hybrid | prev/next | input_value + input_statement |
| Status query | Value | output | field_variable |
field_input: For initialization blocks — user enters a NEW variable namefield_variable: For method call blocks — user selects an EXISTING variable (set variableTypes and defaultType)// field_input
const varName = block.getFieldValue('VAR') || 'defaultVar';
// field_variable
const varField = block.getField('VAR');
const varName = varField ? varField.getText() : 'defaultVar';
// Global object — use directly
const serialPort = block.getFieldValue('SERIAL') || 'Serial';Use these in field_dropdown options — auto-populated at runtime:
| Variable | Usage |
|---|---|
${board.i2c} | I2C interface list (Wire selector) |
${board.digitalPins} | Digital pin list |
${board.analogPins} | Analog pin list |
${board.serialPort} | Serial port list |
${board.serialSpeed} | Baud rate list |
${board.interruptPins} | Interrupt pin list |
${board.interruptMode} | Interrupt mode list |
Register dynamic extensions in generator.js. Always unregister before registering:
if (Blockly.Extensions.isRegistered('ext_name')) {
Blockly.Extensions.unregister('ext_name');
}
Blockly.Extensions.register('ext_name', function() { /* ... */ });All injection methods take (tag, code) and auto-deduplicate by tag.
#include <Lib.h> // addLibrary(tag, code)
#define MACRO val // addMacro(tag, code)
Type globalVar; // addVariable(tag, code)
MyClass obj; // addObject(tag, code)
void helper() {} // addFunction(tag, code, isGlobal?)
void setup() {
Serial.begin(9600); // addSetupBegin — bus-level init ONLY
sensor.begin(); // addSetup — device/sensor init
attachCb(handler); // addSetupEnd — callbacks, depends on prior init
}
void loop() {
btn.tick(); // addLoopBegin — polling/tick calls
// [user blocks here]
}Serial — Always use ensureSerialBegin(), NEVER write Serial.begin() directly:
// ✅ Correct
ensureSerialBegin('Serial', generator); // default 9600
ensureSerialBegin('Serial', generator, 115200); // custom baud
ensureSerialBegin(serialPort, generator, baud); // dynamic
// ❌ FORBIDDEN
generator.addSetupBegin('serial_begin', 'Serial.begin(9600);');I2C — Use wire_${wireName}_begin key for deduplication:
const wire = block.getFieldValue('WIRE') || 'Wire';
generator.addLibrary('Wire', '#include <Wire.h>');
const wireBeginKey = `wire_${wire}_begin`;
if (!generator.setupCodes_ || !generator.setupCodes_[wireBeginKey]) {
generator.addSetup(wireBeginKey, wire + '.begin();\n');
}SPI — Use spi_${spiName}_begin key for deduplication:
const spi = block.getFieldValue('SPI') || 'SPI';
generator.addLibrary('SPI', '#include <SPI.h>');
generator.addSetup(`spi_${spi}_begin`, spi + '.begin();\n');Initialization blocks with field_input MUST implement a rename listener:
if (!block._varMonitorAttached) {
block._varMonitorAttached = true;
block._varLastName = block.getFieldValue('VAR') || 'defaultVar';
registerVariableToBlockly(block._varLastName, 'VarType');
const varField = block.getField('VAR');
if (varField) {
const orig = varField.onFinishEditing_;
varField.onFinishEditing_ = function(newName) {
if (typeof orig === 'function') orig.call(this, newName);
const ws = block.workspace || Blockly.getMainWorkspace?.();
const oldName = block._varLastName;
if (ws && newName && newName !== oldName) {
renameVariableInBlockly(block, oldName, newName, 'VarType');
block._varLastName = newName;
}
};
}
}return 'code;\n';return [expr, generator.ORDER_ATOMIC];return ''; (empty string — event-driven, not in main flow)return 'conditional_code;\n'; (returned code runs inside parent callback)// Extract input value (most cases use ORDER_ATOMIC)
const val = generator.valueToCode(block, 'INPUT', generator.ORDER_ATOMIC) || '0';
// Return value block
return [varName + '.read()', generator.ORDER_FUNCTION_CALL];Access runtime board config via window['boardConfig']:
const boardConfig = window['boardConfig'];
// boardConfig.core — e.g. 'esp32:esp32', 'arduino:avr'
// boardConfig.name — board display name
// boardConfig.i2c — I2C interface list
// boardConfig.digitalPins — digital pin listNEVER modify window['boardConfig'] directly — use independent storage like window['customXxx'].
All input_value slots MUST have shadow blocks:
{
"kind": "block",
"type": "sensor_read",
"inputs": {
"TIMEOUT": {"shadow": {"type": "math_number", "fields": {"NUM": 1000}}}
}
}Organize blocks by user cognitive flow using label separators:
{
"kind": "category",
"name": "SensorLib",
"contents": [
{"kind": "label", "text": "Setup"},
{"kind": "block", "type": "sensor_init"},
{"kind": "label", "text": "Read Data"},
{"kind": "block", "type": "sensor_read"}
]
}{
"name": "@aily-project/lib-libname",
"nickname": "Display Name",
"description": "Brief description (<50 chars)",
"version": "1.0.0",
"compatibility": {
"core": [],
"voltage": [3.3, 5]
},
"keywords": ["aily", "blockly"],
"tested": true,
"url": "original library URL"
}Board compatibility shorthand:
"core": [] (empty array = all boards)"core": ["esp32:esp32"]"core": ["arduino:avr", "arduino:megaavr"]"core": ["esp32:esp32", "esp8266:esp8266", "renesas_uno:unor4wifi"]| ❌ Wrong | ✅ Correct |
|---|---|
Write Serial.begin() directly | Use ensureSerialBegin(port, generator) |
Hardcoded Wire key 'WIRE_BEGIN' | Use wire_${wireName}_begin formatted key |
Modify window['boardConfig'] | Use window['customXxx'] for custom storage |
addSetupBegin for sensor init | addSetupBegin is bus-only; use addSetup for sensors |
No shadow blocks for input_value | Always configure shadow blocks in toolbox.json |
| Extension register without unregister | Always unregister() before register() |
addFunction without 3rd param | Pass true when helper function must be globally visible |
Skip ensureSerialBegin in quick ops | Quick operations using Serial.println need it too |
input_value have shadow blocks in toolbox.jsonensureSerialBegin()wire_${wire}_begin key deduplicationspi_${spi}_begin key deduplicationaddSetupBegin only used for bus-level initializationwindow['boardConfig']field_input blocks© ailyProject, GPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in public/skills/library-migration-guide of ailyProject/aily-blockly.
Open the folder on GitHubat commit 4aace5a
Library Migration Guide next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Library Migration Guide this skillailyProject/aily-blockly | 3.8k | — | ~3.1k | Automated safety check: Pass | GPL-3.0 | |
| Migrate Internal Package into GhostTryGhost/Ghost | 56k | — | ~3.8k | Automated safety check: Pass | MIT | |
| Next Upgradevercel-labs/openreview | 1.7k | 6 repos | ~502 | Automated safety check: Pass | None | |
| RuView Hardware Setupruvnet/RuView | 97k | — | ~1.8k | Automated safety check: Notes | MIT | |
| Esp32 Firmware Engineeralxv2016/folloup-sticky | 116 | 1 repos | ~3.8k | Automated safety check: Pass | GPL-3.0 | |
| RuView mmWave Radar Setupruvnet/RuView | 97k | — | ~907 | Automated safety check: Notes | MIT |
TryGhost/Ghost
Moves a package from another TryGhost repository into Ghost as an internal workspace package while keeping its Git history, with checkpoints for the steps that need an administrator.
vercel-labs/openreview
Upgrade Next.js to the latest version following official migration guides and codemods
ruvnet/RuView
Brings a RuView CSI sensing node online by building ESP32-S3 or ESP32-C6 firmware, flashing the board, provisioning WiFi and checking the serial output.
alxv2016/folloup-sticky
ESP32 firmware engineering for ESP-IDF projects. An agent skill from alxv2016/folloup-sticky.
ruvnet/RuView
Sets up and runs 60 GHz and 24 GHz mmWave radar sensing on ESP32 boards in RuView, alone or fused with WiFi CSI.
FastLED/FastLED
Firmware crash analysis, stack trace decoder, and register dump interpreter for ESP32/ARM/AVR platforms.
ailyProject/aily-blockly
ABS 语法快速参考:权威 ABS 规则与示例 skill,覆盖块连接类型、参数顺序、语句输入、变量引用与常见示例。触发词:ABS、语法、块脚本
ailyProject/aily-blockly
Aily Blockly implementation workflow for scoped library evidence, ABS editing, workspace synchronization, and focused validation.
ailyProject/aily-blockly
Analyze indexed Aily chat session history for prior decisions, tool executions, project summaries, usage tips, and session-store reindexing.
ailyProject/aily-blockly
Blockly project planning and creation workflow for no-project hardware requests.
ailyProject/aily-blockly
Review uncommitted code changes
Categories
Complete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format. Library Migration Guide is an agent skill from ailyProject/aily-blockly. Complete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format.
Library Migration Guide fits situations like: tasks that involve Embedded systems; tasks that involve Code migrations.
Run `npx skills add ailyProject/aily-blockly --skill library-migration-guide -a claude-code`. Or copy the skill folder (public/skills/library-migration-guide in ailyProject/aily-blockly) into .claude/skills/library-migration-guide in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ailyProject/aily-blockly --skill library-migration-guide -a codex`. Or copy the skill folder (public/skills/library-migration-guide in ailyProject/aily-blockly) into .agents/skills/library-migration-guide in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ailyProject/aily-blockly --skill library-migration-guide -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/library-migration-guide, .gemini/skills/library-migration-guide, .github/skills/library-migration-guide and .opencode/skills/library-migration-guide in your project.
Going by SKILL.md and its folder, Library Migration Guide needs the command-line tools its instructions call (npm). Our summary lists: Node.js.
SKILL.md names 1 domain. In commands or code: blockly.diandeng.tech; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Library Migration Guide is published under the GPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.1k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Library Migration Guide: Migrate Internal Package into Ghost (TryGhost/Ghost, 56k stars), Next Upgrade (vercel-labs/openreview, 1.7k stars), RuView Hardware Setup (ruvnet/RuView, 97k stars) and Esp32 Firmware Engineer (alxv2016/folloup-sticky, 116 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ailyProject (a GitHub organization) maintains it in ailyProject/aily-blockly, which has 3,834 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on October 9, 2026.
Source: ailyProject/aily-blockly on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.