> ## Documentation Index
> Fetch the complete documentation index at: https://docs.makershq.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tauri SDK reference

> Look up the updater contract, native window permissions, and headless presentation hooks.

Inside `ReleaseNotesHost`, call `useReleaseNotes()` to open history or check for an update. For the complete host, adapter, and permissions, see [Add release notes to Tauri](https://docs.makershq.dev/integrations/release-notes/tauri.md).

```tsx theme={null}
import { useReleaseNotes } from '@makershq/react/tauri'

export function CheckForUpdates() {
  const { checkForUpdates } = useReleaseNotes()
  return <button onClick={() => void checkForUpdates().catch(console.error)}>Check for updates</button>
}
```

## Updater contract

```ts theme={null}
export interface AvailableUpdate {
  version: string
  notes?: string
}

export type InstallProgress =
  | { phase: 'downloading'; downloadedBytes: number; totalBytes?: number }
  | { phase: 'installing' | 'restarting' }

export interface AppUpdater {
  check(): Promise<AvailableUpdate | null>
  install(
    version: string,
    reportProgress: (progress: InstallProgress) => void,
  ): Promise<void>
  cancel?(): Promise<void>
}
```

Your main window owns the candidate and native handle. `check()` returns an eligible version or `null`. `install()` must verify the selected version, flush pending writes, report progress, install, and restart. Implement `cancel()` only if the underlying updater supports cancellation. See the [complete updater example](https://docs.makershq.dev/integrations/release-notes/tauri.md#consumer-owned-updater).

Background notifications respect the skipped version. A manual check bypasses that preference. A secondary Settings window waits up to 15 seconds for main to connect. Handle a rejected request in your menu and let the visitor retry.

## Existing secondary settings window

If your app already opens a separate settings window, mount the same root in that window and render `ReleaseNotesSettings` in its Updates tab. The settings controls connect to the main host; they stay disabled until its current state arrives. The secondary window does not run the updater callbacks or persist preferences. Keep the main root mounted even when the settings window is closed.

The reader and update prompt return focus to the settings window that opened them when closed. The main window can remain hidden. A single-window app uses the normal host setup without this additional capability.

Add this optional local capability, replacing `settings-window` with your existing window's actual label:

```json theme={null}
{
  "identifier": "consumer-settings",
  "windows": ["settings-window"],
  "permissions": [
    "core:event:allow-listen",
    "core:event:allow-unlisten",
    "core:event:allow-emit-to"
  ]
}
```

Keep this capability local, without remote origins. Retain your settings window's existing app permissions separately; the release integration adds only these event permissions there. Store, window-creation and updater permissions belong to the main host.

## Theme and content security policy

Pass `system`, `light`, or `dark` to the main host. In native mode it synchronizes the SDK windows and title bars, using `core:window:allow-set-theme` in main. In headless mode the app owns native appearance. Embedded Settings uses your app’s semantic color variables when available.

If your app defines a CSP, add `https://makershq.dev` to `connect-src`, alongside existing Tauri IPC and app-owned updater endpoints. Permit the API origin and the actual redirected storage/CDN and external Markdown image origins in `img-src`. An API-origin-only image policy can block the final signed-image redirect. Keep your existing restrictions; do not allow arbitrary remote pages access to native capabilities.

## After-update behavior

The first launch records the installed native version. On a later upgrade the SDK requests the exact published note. It waits for a fresh matching render before acknowledging it. Missing or offline notes retry on focus or reconnect. Changing build metadata counts as a new installed release. The same version and downgrades stay quiet.

## Headless Tauri UI

Set `presentation="headless"` on the host when you supply your own Settings, reader, or update surface. Choose the mode at startup and remount the host to change it. Keep the app’s updater in main. In headless mode the app owns placement, focus, and window lifecycle.

`useReleaseNotes()` adds `state`, `reader`, `update` and `setShowAfterUpdate(value)` to its existing actions. `ReleaseNotesActions` retains its original three-method type; `ReleaseNotesResult` extends it. `state` contains readiness, presentation mode, project/app metadata, preferences, update status/candidate/progress, actionable `canCancel` and recoverable `error`. Disable custom controls until `state.ready`. These fields contain no updater handles or private request IDs.

The optional presentations are independent, so a reader and update surface can coexist:

* `reader` supplies `version` (undefined for history), `originWindowLabel`, `dismiss()` and safe `onReleaseRendered(release, { cached })`.
* `update` supplies `originWindowLabel` and no-argument `install()`, `skip()`, `cancel()` and `dismiss()`.

Use `originWindowLabel` to decide which existing window should present a request, or route it according to your app's policy. Descriptors bind their callbacks to a private request identity and exact candidate; stale callbacks cannot act on replacement or retried presentations, even for the same version. Dismissal hides UI without acknowledging notes or cancelling installation. Install/Cancel promises resolve when the command is accepted; observe progress and failures in `state`. Skip waits for preference persistence. Catch rejected user-action promises for transport/configuration failures. Reader render notification returns void, handles transport/persistence rejection safely, and reports failure through shared state.

```tsx theme={null}
import { ReleaseNotes } from '@makershq/react'
import { useReleaseNotes } from '@makershq/react/tauri'

export function AppOwnedUpdates() {
  const { state, reader, update, open, checkForUpdates, setShowAfterUpdate } =
    useReleaseNotes()
  return (
    <section>
      <p>Installed {state.currentVersion}</p>
      <label>
        <input
          type="checkbox"
          disabled={!state.ready}
          checked={state.preferences.showAfterUpdate}
          onChange={(event) =>
            void setShowAfterUpdate(event.target.checked).catch(() => undefined)
          }
        />
        Show release notes after updating
      </label>
      <button
        disabled={!state.ready}
        onClick={() => void open().catch(() => undefined)}
      >
        Read changes
      </button>
      <button
        disabled={
          !state.ready ||
          state.status === 'checking' ||
          state.status === 'progress'
        }
        onClick={() => void checkForUpdates().catch(() => undefined)}
      >
        Check updates
      </button>
      {state.error && <p role="alert">{state.error}</p>}
      {reader && (
        <section aria-label="Our release notes">
          <ReleaseNotes
            projectId={state.projectId}
            version={reader.version}
            onReleaseRendered={reader.onReleaseRendered}
          />
          <button onClick={() => void reader.dismiss().catch(() => undefined)}>
            Close notes
          </button>
        </section>
      )}
      {update && (
        <section aria-label="Our updater">
          <p>
            {state.status === 'current'
              ? 'You are up to date'
              : state.candidate?.version}
          </p>
          {state.status === 'available' && (
            <>
              <button
                onClick={() => void update.install().catch(() => undefined)}
              >
                Install
              </button>
              <button onClick={() => void update.skip().catch(() => undefined)}>
                Skip version
              </button>
            </>
          )}
          {state.status === 'progress' && <p role="status">Updating…</p>}
          {state.canCancel && (
            <button onClick={() => void update.cancel().catch(() => undefined)}>
              Cancel download
            </button>
          )}
          <button onClick={() => void update.dismiss().catch(() => undefined)}>
            Dismiss
          </button>
        </section>
      )}
    </section>
  )
}
```

For native links, supply your app's HTTP(S) opener through `ReleaseNotes.openExternal`; the browser default is a safe external anchor. For a completely custom reader, use `useReleaseNotesReader` and `ReleaseMarkdown`, and notify the active `reader.onReleaseRendered` only after the matching document commits. Cached rendering, dismissal and history never acknowledge an automatic installed-version request. Missing publication remains retryable; an already-open manual reader is preserved on later automatic triggers.

Keep the app, store, and updater permissions needed by main. Custom secondary windows need their own local event permissions. A headless app can omit SDK child-window capabilities and window creation permissions unless its own windows use them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.