# AI execution Run installed Claude/Codex tools or use the optional macOS Codex supervisor. Source: https://legend.so/spark/ai/ ## [Installed command-line tools](https://legend.so/spark/ai/#installed-command-line-tools) `@legendapp/spark/ai` owns execution helpers for installed Claude and Codex CLIs. It uses Spark processes and requires a desktop process host. Installation, login, prompts, provider policy, and data validation remain application/user responsibilities. Importing helpers does not run a prompt. ```ts import { getAICommandAvailability, runAITool, parseAIJson } from '@legendapp/spark/ai'; const availability = await getAICommandAvailability({ preferredTool: 'codex' }); if (availability.preferredTool) { const result = await runAITool({ tool: availability.preferredTool, prompt: 'Return a JSON object containing a greeting.', timeoutMs: 30_000, }); if (result.exit.type === 'exited' && result.exit.code === 0) { const value = parseAIJson(result.output); console.log(value); } } ``` Availability is an advisory installed-command probe, not authenticated access. `runAITool` retains the process result, including raw stdout/stderr bytes, discriminated exit, timeout/abort, and truncation. `output` is trimmed UTF-8 stdout, falling back to stderr if stdout is empty. Nonzero exit and termination are results; operational failures reject. `signal`, `cwd`, and `timeoutMs` follow the process contract. Codex model/reasoning settings go in `invocationOptions.codex`. The Codex exec recipe uses ephemeral execution and ignores user config/exec-policy rule files while retaining the CLI's sandbox/approval mechanism. Protocol/flags depend on the installed tool version. `buildAIInvocation` returns the argument recipe without execution. JSON helpers extract raw/fenced/prose-wrapped content and return unknown/null; validate application schemas before using it. `formatAIErrorOutput(output, { maxLength })` bounds error previews. No React mount is required. ## [Native Codex app-server](https://legend.so/spark/ai/#native-codex-app-server) `@legendapp/spark/ai/codex` supplies an optional **macOS** native supervisor, with exec fallback when its app-server protocol is unavailable. `getCodexAvailability()` safely reports unsupported hosts/missing modules and installed-command information. A consuming app needs the matching native capability and rebuilt host. ```ts import { runCodexPrompt, shutdownCodex } from '@legendapp/spark/ai/codex'; const result = await runCodexPrompt('Return a greeting as JSON.', { outputSchema: { type: 'object', properties: { greeting: { type: 'string' } }, required: ['greeting'], additionalProperties: false, }, reasoningEffort: 'low', timeoutMs: 120_000, }); console.log(result.output); await shutdownCodex(); ``` The final line represents application-owned shutdown. The supervisor is process-wide. `cancelActiveCodexRuns()` cancels all accepted runs, including startup, and returns a count. `shutdownCodex()` cancels active runs and stops the server; later execution restarts it. These are not per-component or per-request cleanup operations. This backend does not promise a per-request AbortSignal. `timeoutMs` is a whole number from 1,000 to 86,400,000 milliseconds. The isolated Codex home reuses existing authentication; the library does not acquire credentials. Pre-ack notification buffering is bounded at 16 MiB and excessive buffering fails explicitly. See [the AI guide](https://github.com/LegendApp/legend-spark/blob/main/docs/ai.md). [View Markdown](https://legend.so/spark/ai.md)[Report a documentation correction](https://github.com/LegendApp/legend-docs/issues/new?title=Docs%3A+AI+execution&body=Page%3A+https%3A%2F%2Flegend.so%2Fspark%2Fai%0A%0AWhat+is+incorrect+or+missing%3F%0A%0AExpected+behavior+or+supporting+source%3A%0A) --- # Camera VisionCamera previews, permissions, and automatic native compatibility patches. Source: https://legend.so/spark/camera/ `@legendapp/spark/camera` exposes VisionCamera components, device/permission hooks, photo/video outputs, and session APIs with upstream semantics. It also exports `NitroImage` and its `Image` type. Advanced APIs remain available from `react-native-vision-camera` directly. ## [Camera preview](https://legend.so/spark/camera/#camera-preview) ```tsx import { Camera, useCameraDevices, useCameraPermission, usePhotoOutput, } from '@legendapp/spark/camera'; import { Button } from 'react-native'; export function PhotoCamera() { const devices = useCameraDevices(); const { hasPermission, requestPermission } = useCameraPermission(); const photoOutput = usePhotoOutput({ containerFormat: 'jpeg' }); if (!hasPermission) { return