Skill v1.0.1
currentAutomated scan100/100+4 new
version: "1.0.1" name: write-device-skill description: >- Use when authoring a DEVICE-SKILL.md for a new Resident-based firmware project. Walks the user through hardware, Lua module surface, examples, and constraints. Triggered when the user says "write a device skill", "set up DEVICE-SKILL.md", or invokes /resident:write-device-skill.
write-device-skill
Help the user produce a DEVICE-SKILL.md for a Resident-based firmware project. The output is a single Markdown file at the firmware project root that documents the device-specific Lua surface — hardware, modules, examples, constraints. Sandbox-generic content (lifecycle callbacks, ctx, log, time, store, events) is NOT in DEVICE-SKILL.md; it lives in Resident's own docs and is loaded by the create-app skill.
Audience
DEVICE-SKILL.md is written for Lua app authors targeting the device sandbox. The reader is someone composing a Lua app and pushing it to a running device — they do not have the firmware source open and cannot change it. Frame everything from that perspective: the runtime contract (what modules and variables exist, what they do, what ranges are valid). Do NOT describe the C++ firmware layer — no SandboxConfig fields, no driver registration, no "to enable X the firmware would need to..." asides. If a capability isn't exposed to Lua, just say so plainly and move on.
What you need
- Firmware project root — defaults to
cwd. Ask if not in one. - Device identity — short name (e.g. "M5StickC Plus2", "<My Hardware Startup> lamp").
- Driver surface — which
Resident::Driver/Resident::Extension
subclasses the firmware registers, and what each one's name() and Lua module functions are.
Workflow
- Read the template at
${CLAUDE_PLUGIN_ROOT}/skills/write-device-skill/tools/template.md. ${CLAUDE_PLUGIN_ROOT} is set by Claude Code to the absolute path of the installed plugin — always use it to reference bundled files; the CWD is the user's project, not the skill directory.
- Read the reference example at
${CLAUDE_PLUGIN_ROOT}/skills/write-device-skill/tools/example.md — that's the seeded M5StickC Plus2 DEVICE-SKILL.md, useful as a quality bar.
- Ask the user (one question at a time):
- Device name + a one-paragraph overview.
- Hardware list (screen? sensors? audio? buttons? indicators?).
For each, ask for size/units/coordinate frames.
- Driver modules: which Lua module names are exposed (e.g.
screen,
imu)? For each, ask the user to walk through the available functions, signatures, and any defaults/ranges.
- 3–6 example apps that exercise the modules. The agent can draft
these from the hardware description; user confirms.
- Constraints (dimensions, ranges, memory).
- Optional: device-specific practical tips.
- Optional: a
## Validation stubsLua block (see template.md and
example.md for format). This makes validate-app produce realistic getter return values instead of nil, so apps that compute against screen.width() etc. validate cleanly. Skip if the device has no numeric or multi-value getters.
- Write the result to
<project-root>/DEVICE-SKILL.md. Do NOT include
sandbox-generic content (lifecycle, ctx, log/time/store/events).
- Show the user a diff/summary and confirm before writing.
Pointers when interviewing
- A driver's Lua module name is whatever its
Extension::name()returns
in C++. If the user has firmware source open, point them at the Driver subclass declarations.
- Module function signatures come from
LuaModule::method<>/
staticMethod / constant calls in registerModule().
- For sensors that return multiple values (e.g.
imu.accel()returning
ax, ay, az), Lua-style multi-return is the convention.
- Coordinate frames matter — document body frame, screen orientation,
and the sign conventions of any axis.
What NOT to put in DEVICE-SKILL.md
These are sandbox-generic and live in Resident's own docs (loaded by create-app). DON'T duplicate them per device:
- App lifecycle:
init(ctx),on_tick(ctx, dt_ms),on_event(ctx, event) - The
ctxtable fields (time_ms,generation_id) - Built-in modules:
log.*,time.*,store.*,events.*,surfaces.* - Lua's own libraries (
math.*,string.*,table.*)
If the firmware exposes a device-specific module that overlaps with one of these names, document it under Lua Modules — but don't restate the universal modules.