| name | device-it |
| description | Put a local web project on a device Home Screen / launcher as a launchable, fullscreen, offline-capable app with its own icon and name — iPhone, iPad, Android, or desktop browser. Use when the user says device-it, "put this on my phone/iPad/tablet", "make this an installable app", "install on my device", "home screen app", or wants the on-device sibling of app-it (which makes a Mac Dock app). Builds the project, applies a PWA transform (manifest, icons, service worker) to the built output only, deploys to a stable HTTPS URL, and installs via the pocket MDM on Apple devices (zero-touch: icon just appears) or a QR/Add-to-Home-Screen link everywhere. Also handles update, remove, list, doctor, and one-time setup/enrollment. Legacy alias: ipad-it. |
device-it — a web project as a real app on any of your devices
Sibling to app-it: app-it makes a macOS Dock app; device-it makes a Home Screen /
launcher app on the devices you carry. One PWA build serves them all —
- iPhone / iPad / Android / desktop Chrome-Edge: the scan lane installs a fullscreen,
offline app with its own icon everywhere. Android/desktop get an even cleaner native install
than iOS. This lane needs no accounts and works today.
- Apple devices, once enrolled: the zero-touch lane pushes the icon so it just appears,
no taps. Apple-only (it rides Apple's MDM); Android/desktop always use the scan lane.
Lane decided by one check: if ~/.device-it/config.json exists, an Apple device is enrolled
→ zero-touch lane: push the web clip, the icon appears with no taps. Otherwise → scan lane:
QR/iMessage link + Add to Home Screen (≈2 taps; Android/desktop show a native install prompt),
and mention that /device-it setup (~10 min, once) upgrades Apple devices to zero-touch. Never
block the scan lane on setup — it's the universal one.
Non-negotiables
- Run
scripts/inspect.sh from the project root first; trust its output over docs.
- Never modify project source. The PWA transform operates on the BUILT output dir only.
- Decide defaults yourself (name from package.json, icon by discovery); ask only when
truly ambiguous. Missing icon → generate a clean monogram placeholder and say so.
- The web clip URL must be the STABLE production URL, never a per-deploy hash URL.
- Same slug = same Vercel project, same profile PayloadIdentifier — updates are in-place.
- Verify before declaring victory: HTTP truth always, offline truth via Playwright when
available, device truth via MDM acknowledgment. Report honestly what was not verifiable.
- Clean up what you start: temp servers down, funnel closed after enrollment flows
(
mdm-down.sh after pushes; the MDM's default posture is OFF between installs).
- Public URL = public app. Don't add auth walls (they break offline) unless asked.
Pipeline (default invocation)
One command does everything — inspect, build, icons, PWA transform, deploy-driver
auto-pick, deploy, verify, web clip, then the zero-touch lane (MDM push) or the
scan lane (QR+iMessage), plus registry bookkeeping:
bash /path/to/skills/device-it/scripts/run.sh <project-dir> [--icon img] [--name "Name"] [--slug slug] [--driver name]
bash /path/to/skills/device-it/scripts/run.sh --url https://already-hosted.app --name "Name"
bash /path/to/skills/device-it/scripts/run.sh remove <slug>
Deploy needs NO specific vendor: deploy/pick.mjs uses whatever is already authed
(vercel → netlify → cloudflare → gh-pages) and otherwise falls back to an anonymous
Netlify deploy — no account, claimable for 1 hour (run.sh auto-opens the claim page;
one GitHub-SSO click makes it permanent and free). Anonymous sites are password-gated
until claimed (password is printed) — tell the user to CLAIM FIRST, then install.
See references/hosting.md for all drivers and their live-verified quirks.
Icon discovery order (run.sh does this itself): --icon → inspect's ICON_CANDIDATES →
the app-it Mac app's .icns for the same project root → generated monogram (never blocks).
Read run.sh output: URL, VERIFY, LANE (zero-touch or scan), PROFILE — relay per report-template.
Individual stages remain callable (inspect.sh, icons.sh, pwaify.mjs, deploy/vercel.sh,
verify.mjs, webclip.mjs, mdm/*, qr.sh, registry.mjs) for debugging or partial reruns.
The PWA transform also injects a dismissible iOS-only "tap Share → Add to Home Screen"
hint that renders only in Safari (never in the installed app) — scan-lane users see their
own install instructions on screen.
Other verbs
- update: rerun the pipeline; skip webclip+push unless name/icon/URL changed (SW
delivers content updates on next launch by itself).
- remove :
mdm-push.mjs remove --identifier dk.deviceit.<slug> (icon vanishes),
optionally vercel remove deviceit-<slug> --yes, then registry.mjs remove.
- list:
registry.mjs list.
- doctor:
scripts/doctor.sh — toolchain, deploy auth, MDM health, push-cert expiry.
- setup: one-time enrollment. Follow
references/onboarding.md exactly; it marks the
four [HUMAN] moments. Ends by writing ~/.device-it/config.json (the setup-done flag).
Reference map
references/onboarding.md — one-time zero-touch-lane setup wizard (agent-driven).
references/mdm-protocol.md — nanomdm endpoints, command plists, lifecycle, renewal.
references/hosting.md — deploy driver contract, vercel details, custom domains, caveats.
references/report-template.md — the exact final report to give the user.
Honest limits (state them, don't hide them)
- Offline starts after the FIRST launch (SW caches then) — no lane can launch the app for you.
- Backend-dependent apps: shell works offline, API calls need their backend.
- The zero-touch lane is Apple-only. Android/desktop always use the scan lane (1-tap install
there, so no real loss). Non-Apple devices never need setup.
- Apple device asleep during push → icon appears when it wakes ("pushed", not "confirmed").
- Yearly APNs cert renewal (~3 min); doctor warns 30 days out.