# Builtin Commands

zero-native provides built-in bridge commands for window management, layered WebViews, and native dialogs. These are controlled by the `builtin_bridge` policy in `RuntimeOptions`, separate from app-defined commands.

## Window commands

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>Required permission</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>zero-native.window.list</code></td>
      <td><code>window</code></td>
      <td>List all open windows</td>
    </tr>
    <tr>
      <td><code>zero-native.window.create</code></td>
      <td><code>window</code></td>
      <td>Create a new window</td>
    </tr>
    <tr>
      <td><code>zero-native.window.focus</code></td>
      <td><code>window</code></td>
      <td>Focus a window by ID</td>
    </tr>
    <tr>
      <td><code>zero-native.window.close</code></td>
      <td><code>window</code></td>
      <td>Close a window by ID</td>
    </tr>
  </tbody>
</table>

Window commands are available through `window.zero.windows.*` when `js_window_api` is `true`, but the runtime still checks the request origin and the `window` permission when permissions are configured. Use an explicit `builtin_bridge` policy when you want per-command origin lists.

## WebView Commands

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>Required permission</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>zero-native.webview.create</code></td>
      <td><code>window</code></td>
      <td>Create a named WebView in a window</td>
    </tr>
    <tr>
      <td><code>zero-native.webview.list</code></td>
      <td><code>window</code></td>
      <td>List WebViews in the calling window</td>
    </tr>
    <tr>
      <td><code>zero-native.webview.setFrame</code></td>
      <td><code>window</code></td>
      <td>Move or resize a WebView</td>
    </tr>
    <tr>
      <td><code>zero-native.webview.navigate</code></td>
      <td><code>window</code></td>
      <td>Navigate a WebView</td>
    </tr>
    <tr>
      <td><code>zero-native.webview.setZoom</code></td>
      <td><code>window</code></td>
      <td>Set page zoom from <code>0.25</code> to <code>5.0</code></td>
    </tr>
    <tr>
      <td><code>zero-native.webview.setLayer</code></td>
      <td><code>window</code></td>
      <td>Change native stack order</td>
    </tr>
    <tr>
      <td><code>zero-native.webview.close</code></td>
      <td><code>window</code></td>
      <td>Close a WebView</td>
    </tr>
  </tbody>
</table>

WebView commands are available through `window.zero.webviews.*` when `js_window_api` is `true`. They use the same origin and `window` permission checks as window commands. WebView URLs are also checked against `security.navigation.allowed_origins`. Backend-specific gaps reject with `invalid_request` and an actionable unsupported-backend message.

If `windowId` is omitted, the runtime uses the window that sent the bridge message. If provided, `windowId` must match that same calling window. Child WebViews are isolated by default and receive `window.zero` only when created with `bridge: true`. The startup WebView is always listed as `main`; that label is reserved and cannot be used for child WebView creation.

## Dialog commands

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>zero-native.dialog.openFile</code></td>
      <td>Show a file open dialog</td>
    </tr>
    <tr>
      <td><code>zero-native.dialog.saveFile</code></td>
      <td>Show a file save dialog</td>
    </tr>
    <tr>
      <td><code>zero-native.dialog.showMessage</code></td>
      <td>Show a message dialog</td>
    </tr>
  </tbody>
</table>

Dialog commands are **always default-deny** and require an explicit `builtin_bridge` policy.

## Enabling builtin commands

```zig
const app_permissions = [_][]const u8{zero_native.security.permission_window};

.security = .{
    .permissions = &app_permissions,
    .navigation = .{ .allowed_origins = &.{ "zero://app" } },
},
.builtin_bridge = .{
    .enabled = true,
    .commands = &.{
        .{ .name = "zero-native.window.list", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.window.create", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.create", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.list", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.setFrame", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.navigate", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.setZoom", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.setLayer", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.webview.close", .permissions = .{ "window" }, .origins = .{ "zero://app" } },
        .{ .name = "zero-native.dialog.openFile", .origins = .{ "zero://app" } },
        .{ .name = "zero-native.dialog.showMessage", .origins = .{ "zero://app" } },
    },
},
```

## JavaScript usage

```javascript
await window.zero.windows.create({
  label: "tools",
  title: "Tools",
  width: 420,
  height: 320,
});

const preview = await window.zero.webviews.create({
  label: "preview",
  url: "https://example.com",
  frame: { x: 24, y: 24, width: 480, height: 320 },
  layer: 10,
  bridge: false,
});

await preview.setZoom(1.25);
await preview.setLayer(20);
await preview.close();

const files = await window.zero.invoke("zero-native.dialog.openFile", {
  title: "Select a file",
  allowMultiple: true,
});

const result = await window.zero.invoke("zero-native.dialog.showMessage", {
  style: "warning",
  title: "Confirm",
  message: "Are you sure?",
  primaryButton: "Yes",
  secondaryButton: "No",
});
```

See also: [Multiple WebViews](/webviews) for frame and layer semantics, [Dialogs](/dialogs) for the full dialog type reference, and [Security](/security) for policy details.
