Take one photo, or record one audio clip, through the HOST's capture UI (BROWSER_CAPABILITIES_SPEC §3 grade 1).

The host opens the device at its own origin, draws the viewfinder, and hands you the bytes when the user presses Done. You are never in the loop while the device is live — that is the point of the design, not a limitation of it:

  • The capture UI is drawn by the host, so a user can trust it the way they trust the sign-in dialog. Do not build a lookalike; imitating host chrome is spoofing.
  • While the device is open the host shows a persistent "camera on" / "microphone on" indicator in its own chrome, for the whole session. You cannot hide it and should not try to.
  • If the user cancels, this rejects cancelled and nothing was recorded. There is no partial result — do not write error handling that hopes for one.
import { capturePhoto, requestMount, openFs } from '@immediately-run/sdk';

try {
const { bytes, mimeType } = await capturePhoto({ facing: 'environment' });
const mount = await requestMount(); // the user picks a space to save into
const fs = openFs(mount); // writeFile is a METHOD on the MountFs
await fs.mkdir('photos', { recursive: true }); // writeFile does not create parents
await fs.writeFile(`photos/latest.${mimeType === 'image/png' ? 'png' : 'jpg'}`, new Uint8Array(bytes));
} catch (e) {
if ((e as { code?: string }).code === 'cancelled') return; // the user said no
throw e;
}

(The extension follows mimeType because the HOST chooses the format — do not assume JPEG. openAppFs() is the variant that writes to your own app space with no pick.)

Two things must BOTH be true, exactly as for any other task:

  1. immediately.run.invokes lists capture-photo (or capture-audio);
  2. your app holds task:invoke and device:camera (or device:microphone) — declare them in immediately.run.capabilities so the user can grant them.

Rejects with .code: cancelled (the user dismissed the capture — nothing was recorded), forbidden (you lack the capability; message: 'browser-denied' means the BROWSER refused immediately.run itself, which your consent cannot fix), unavailable (no such device on this machine, or it would not start), unsupported (this host cannot capture), not-declared, timeout.

Zero-platform alternative, still worth knowing: <input type="file" accept="image/*" capture="environment"> opens the OS camera from inside the sandbox (file choosers are not permission-gated). It needs no capability and no host support; it also gives you no indicator and no host-drawn surface.