by AirsupHQ
Describe any machine in one line. Claude builds a photoreal, physics based, interactive simulation of it in one HTML file, plus the film to post it. An open source Claude Code skill.
# Add to your Claude Code skills
git clone https://github.com/AirsupHQ/machine-skillGuides for using ai agents skills like machine-skill.
See how machine-skill compares with popular alternatives.
machine-skill is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by AirsupHQ. Describe any machine in one line. Claude builds a photoreal, physics based, interactive simulation of it in one HTML file, plus the film to post it. An open source Claude Code skill. It has 87 GitHub stars.
machine-skill's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/AirsupHQ/machine-skill" and add it to your Claude Code skills directory (see the Installation section above). machine-skill ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
machine-skill is primarily written in JavaScript. It is open-source under AirsupHQ on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh machine-skill against similar tools.
No comments yet. Be the first to share your thoughts!
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
You build a machine the way a product studio photographs one and an engineer explains one: the real thing at its real size, in real materials, on a clean studio set, running on real equations. One line in, one HTML file out, and a film in one command.
The output is always:
<name>.html: a single self contained page (three.js 0.170 from jsDelivr, the kit inlined). It opens from disk, from any static host, or inside an iframe.node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:<Category>/<Name>.Open examples/ first. Every example was made from the one line at the top of its page. examples/turbofan.html is the reference: read it end to end before you write anything.
Before you start, picture the frame a viewer sees after three seconds. It must already look like a studio product photograph of the real machine: correct silhouette and proportions, metal that reads as metal, a soft shadow on a paper floor, nothing floating, nothing clipping, nothing placeholder. Then it moves, and every number on screen is computed.
A result is not done while any of these is true:
Write down, in a comment block at the top of the machine script, from what you know (and the web if you have it):
Copy kit/template.html to <name>.html. It has the import map (pinned three@0.170.0), the fonts, a marked block where the kit goes, and the four sections you fill in:
const { THREE, Lab, MAT, GEO, heatGlow, clamp, lerp, approach, fmt } = window.LabKit
const lab = new Lab({ prompt, no, title, sub, size, view, cut }) // 1. the lab
// 2. the parts lab.mesh(GEO..., MAT..., { name, pos, explode, xray, count })
// 3. the solver lab.hero(...); lab.slider(...); lab.onTick((dt, lab) => { ... lab.setHero(...) })
// 4. break, explain, film lab.breakIt(...); lab.how(...); lab.autoFilm(...); lab.start()
Right after copying, run node <skill dir>/scripts/inline.mjs <name>.html: it pastes the kit into the marked block so the page is one self contained file wherever it lives (the template's src="../kit/lab-kit.js" only resolves inside this repo). Then write your machine in the second script block.
Work in metres in the machine's own frame, Y up, the floor at y = 0 unless you set ground. Set size to the longest real dimension; the kit scales the display so every machine sits the same on the set, and the scale bar shows real size.
GEO.lathe([[r, y], ...]) with a CLOSED profile. Walls: GEO.shell(profile, thickness), tubes: GEO.tube(rOut, rIn, h), chamfered discs: GEO.disc(r, h). Corners stay crisp and curves shade smooth automatically.GEO.rotor({ count, axis, r0, r1, chord, thick, camber, twist, pitch, sweep }) builds real cambered, twisted airfoils (NACA thickness) as closed solids and rings them. Use [root, tip] arrays for chord, thick and camber.GEO.gear({ teeth, module, width, bore, helix, spokes, rim }). Mesh two gears at centre distance (z1 + z2) * module / 2 and turn them at the inverse tooth ratio, offset by half a tooth.GEO.pipe(points, r) (closed, capped). Route them along the structure from port to port, never through a part.GEO.bolts(n, R, size, h) on every flange. Springs: GEO.spring(R, wire, turns, len). Boxes: GEO.rbox(w, h, d, r) (always rounded, never sharp). Plates with holes: GEO.extrude(shape, depth).GEO.volume(geo) gives volume and centroid, multiply by the real density.Rules that keep it clean:
GEO.merge / GEO.ring; keep moving groups separate.Use MAT.* presets; they carry measured reflectances so steel, titanium, aluminium, brass and copper look different side by side. Every preset takes overrides (color, roughness, clearcoat, any MeshPhysicalMaterial field) and a finish (micro roughness texture: turned rings on lathe parts, brushed streaks, cast blotches, smudge, knurl).
| Use | Preset |
|---|---|
| shafts, discs, machined parts | MAT.steel, MAT.stainless, MAT.chrome |
| housings, castings | MAT.aluminium, MAT.castIron, MAT.steelDark |
| blades, aerospace | MAT.titanium, MAT.inconel (+ heatGlow) |
| fittings, wiring | MAT.brass, MAT.copper, MAT.gold |
| painted bodies | MAT.paint({ color }), MAT.satin, MAT.anodised({ color }) |
| polymers | MAT.plastic, MAT.rubber, MAT.carbon |
| windows, crystals | MAT.glass, MAT.sapphire, MAT.ruby, MAT.enamel |
| light, flame, hot gas | MAT.glow, heatGlow(material, kelvin) |
Pick a palette like an industrial designer: mostly metals and one or two painted colours, one accent at most. Hot parts glow from the solver's temperature (material.userData.heat.value = T).
Write a small pure function from the input and state to every number you show, with real units and real constants. Integrate dynamics with approach (first order lag: spool up, thermal mass) or rk4 (springs, escapements, pendulums). Then drive the motion from it: an rpm from the solver turns the shaft, a flow from the solver moves the particles, a temperature heats the metal.
lab.hero({ label, unit, max }) then lab.setHero(value, { state, sub, bad }) each tick. state is two or three words (spooling up, take-off, choked flow). sub is one line with 2 or 3 more numbers.lab.slider({ id, label, min, max, value, unit, ends }). A second only if the machine truly needs it.lab.label(obj, 'HP turbine', { at: [x, y, z], value: () => '12,979 rpm' }).lab.how(words, equations) fills "How it is computed": the model in plain words and the equations as written in the code. Say what is simplified.how ("spin shown 1:60"). Never slow the numbers.lab.flow({ paths, count, length, color, parent }): streaks that ride along paths you build from the real flowpath (air through a duct, blood through a pump, water through a puck). Set .speed from the solver and .opacity from lab.state.cut so they show inside the cutaway. Colour by a computed quantity (temperature, pressure).lab.plume({ radius, length, dir, color: 'rocket' | 'jet', shocks }): an exhaust with Mach diamonds; set .power from the solver.lab.sparks.emit(worldPos, n, speed) and lab.shed(mesh, v, w) for breaks: sparks fall with gravity and bounce; a shed part becomes a rigid body that lands on the floor.lab.add/lab.mesh takes explode: [dx, dy, dz] in the parent's frame (metres). Move parts along their assembly axis, outer shells furthest, and keep the core in place. Nothing should cross anything on the way out.cut: { a, b, center, reach } on the Lab. a and b are the directions of the removed region: a = [0,0,1], b = [0,1,0] removes the quarter toward the viewer and up (best for things with an axis); b = a removes a half. Section faces are drawn automatically for every closed solid, with a faint hatch.xray: 'shell' on outer casings turns them to glass with fine edges, so the core shows while it runs.lab.breakIt({ label, run(lab), reset(lab) }). run changes the solver state (a blade released, a valve stuck, a seal blown) and the solver computes the consequence. Show it in the hero (bad: true) and with sparks, debris or shake.Render and READ every image you make. Use the scripts:
node scripts/shot.mjs <name>.html out/review.png # the first look
node scripts/shot.mjs <name>.html out/cut.png --js "lab.toggle('cut', true); lab.toggle('labels', true)"
node scripts/shot.mjs <name>.html out/near.png --js "lab.setView({ az: 70, el: 8, dist: 0.8, target: [x, y, z] })"
node scripts/shot.mjs <name>.html out/film --film 1,4,8,12,17,22,26 # film stills
Do at least four review rounds. In each: whole view, cutaway with labels, exploded, two close ups of joints, and the film stills. Compare against real product photography of the machine in your memory: proportions, part count, materials, how light falls on it. List what is wrong, fix it, render again. Stop only when the list is empty. The shot script prints fps, part count and triangles; keep interactive frame rates above 30.
lab.autoFilm({ runBeat, runSub, breakBeat, breakSub, sliderTo }) writes the standard 28 second story from your machine, in numbered beats with the editorial captions:
It loops: the last camera key returns to the first. For a custom film use lab.film('name', { len, assemble, shots, events }): shots are camera keys { t, az, el, dist, target, fov }, events are { t, beat: ['07', 'Bold sentence.', 'Grey sentence.'], set: { cut: 1 }, slider: { id, to, dur }, cursor: { to: 'slider:id:0.8' | 'button:break' | [x, y], click: true }, do(lab) {} }.
Record (needs Node 18+, Playwright with Chromium, ffmpeg):
node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:Classical/Easy_Lemon
node scripts/record.mjs <name>.html out/<name>-portrait.mp4 --w 1080 --h 1350
The page runs in film mode (?film=1): its clock only moves when the recorder steps it, so every frame is complete and the film is identical every take. The recorder guards every screenshot against the magenta frames a stalled headless GPU can return, and scans the finished film; it exits non zero if any frame is pink. Music from FreePD is CC0; credit the track anyway.
The page is editorial, not a dashboard: a prompt bar, a serif title with an italic subtitle, one huge number with italic units and a thin bar, one line of supporting numbers, one slider. Write like a good caption: short, concrete, no hype, real units with a space (338 kN, 1,750 K, 4.2 L/min), thousands separated. Beat captions are a bold sentence and a grey sentence.
Give the path of the HTML file, the film command, the operating point the solver reaches against the public figure, and anything you simplified. Offer the next machine.
/machine a turbofan jet engine, the kind that pushes a widebody off the runway
Claude researches the real machine, writes down its real dimensions and the physics that make it work, and builds it: a 2.9 m fan of twisted titanium airfoils, a 10 stage compressor, an annular combustor with 22 fuel nozzles, two turbines glowing at the temperatures a Brayton cycle solver computes, on a ground run stand. You drag the throttle and about 340 kN comes out of the cycle, not out of a table. You cut it open and the section faces are solid metal. You throw a fan blade and the solver tells you the imbalance load the case has to hold.
Then one command turns it into a film for your feed.
npx skills add AirsupHQ/machine-skill -g -a claude-code
Then in Claude Code:
/machine a mechanical watch movement, the escapement ticking
You get watch.html: open it, drag, cut, explode, break. To film it:
node ~/.claude/skills/machine/scripts/record.mjs watch.html out/watch.mp4 --music freepd:Classical/Easy_Lemon
Each machine was made from the single line under it. Click one to run it live.
The pages are in examples/: each is one HTML file you can open from disk. More machines are coming; see V2-IDEAS.md, and send yours as a pull request.
| The real machine | Real proportions in metres, 15 to 40 named parts and thousands of solid pieces (blades, teeth, bolts), lathe turned solids, cambered and twisted airfoils, involute gears, routed pipes. A scale bar shows real size. |
| Real materials | Physically based steel, titanium, Inconel, copper, brass, aluminium, paints, polymers, glass and sapphire, with measured reflectances, micro finishes (turned, brushed, cast), clearcoats and heat glow from the solver's temperatures. |
| A studio | A softbox environment with black flags, a soft key shadow, contact shadow, ambient occlusion, bloom, a paper seamless or a night set. It looks like a product photograph before it moves. |
| Real physics | A small solver per machine (Brayton cycle, rocket chamber and nozzle, slider crank and BMEP, torsional oscillator, Cp(lambda, beta), pump curves, Kienzle, Darcy) drives every motion and every number. "How it is computed" shows the equations. |
| Modes | Explode, cutaway with solid section faces, x-ray, slow motion, live labels, pause, and a computed "break it". |
| A film | ?film=1 gives a deterministic clock. One command records a 28 s film in numbered beats: you type one line, Claude builds it part by part, it runs, it opens, it comes apart, it breaks. Music bed included, magenta frame guard and pink scan built in. |
Machine Skill is a standard Agent Skill: a folder with a SKILL.md at its root. This repository is that folder.
| Command | Installs to | |
|---|---|---|
| skills CLI, for you | npx skills add AirsupHQ/machine-skill -g -a claude-code |
~/.claude/skills/machine |
| skills CLI, one project | npx skills add AirsupHQ/machine-skill |
.claude/skills/machine |
| git, for you | git clone https://github.com/AirsupHQ/machine-skill.git ~/.claude/skills/machine |
~/.claude/skills/machine |
| git, one project | git clone https://github.com/AirsupHQ/machine-skill.git .claude/skills/machine |
.claude/skills/machine |
Claude Code picks up new skills in a running session; if the skills folder did not exist when the session started, run /reload-skills.
SKILL.md. Everything else is plain files.kit/template.html, fill the four sections by hand.Type /machine and name the machine. You can also just ask Claude to "build", "simulate" or "show how X works"; the skill loads itself for machines, engines, mechanisms and devices.
/machine a hydroelectric Francis turbine
/machine a Swiss lever escapement, slowed down so I can see the impulse
/machine the gearbox of a 5 MW wind turbine, cut open
/machine a steam locomotive's valve gear, and give me a 30 second video for X
Three habits get the best machines:
--w/--h), or a still for a slide.node scripts/record.mjs examples/turbofan.html out/turbofan.mp4 --music freepd:Classical/Easy_Lemon
node scripts/record.mjs examples/turbofan.html out/turbofan-feed.mp4 --w 1080 --h 1350
node scripts/record.mjs examples/turbofan.html out/stills --stills 3,9,14,19
node scripts/pinkscan.mjs out/*.mp4
The page runs with ?film=1&shot=main: time only moves when the recorder steps it, so every frame is fully rendered and a take is identical every time. --ss 1.5 supersamples, --blur 2 adds motion blur, --fps 60 for very fast motion. Music: any file, URL, or freepd:<Category>/<Name> (CC0 tracks from FreePD via archive.org). The recorder guards every screenshot against the solid magenta frames a stalled headless GPU can return and scans the finished film; it exits non zero if a pink frame got through.
The launch film at the top was directed in a browser page, film/launch.html, that embeds a live machine page and steps it frame by frame.
SKILL.md is what Claude reads: the bar a result must clear, the workflow (research, geometry, materials, solver, effects, modes, four critic rounds, the film), and the writing style on screen.kit/lab-kit.js is the runtime every page inlines (one ES module, no build step, three.js 0.170 from a pinned CDN). Studio, post stack, material library with section caps, geometry builders, explode, cutaway, x-ray, labels, flow streaks, plumes, sparks, rigid debris, the editorial layer and the film timeline.references/solvers.md holds solver recipes with real constants for gas turbines, rockets, piston engines, watches, rotors, pumps, machine tools, porous flow and electric machines.scripts/: shot.mjs (screenshots for the critic rounds, prints fps, parts and triangles), record.mjs (films), pinkscan.mjs, inline.mjs (paste the kit into a pa