# Set up Kiosky with an AI assistant

> A ready-to-copy prompt and the exact steps an AI agent should follow to find a tablet, read and change its config safely, send commands and build Home Assistant automations.

An AI assistant that can run shell commands or make HTTP requests (Claude Code, for example) can configure a Kiosky tablet for you through its local REST API. This page has two parts: a short guide for you, and the exact procedure and safety rules for the agent. The agent should read the whole page.

Everything the agent does uses the documented [REST API](rest-api.md). Machine-readable versions of these docs are at [`/llms.txt`](/llms.txt) and [`/llms-full.txt`](/llms-full.txt), and this page is available as Markdown at `/docs/ai-setup.md`.

## For you: what to prepare

1. **Finish the setup wizard on the tablet**, so it already shows a dashboard. See [Getting started](getting-started.md).
2. **Turn on the REST API.** On the tablet open **Settings, Connections, Remote access** and switch on **REST API & admin page**. Note the port (2323 by default) and the tablet's IP address.
3. **Copy the API token** (**Show** or **Copy** under **API token**).
4. **Give the token to the agent without pasting it into the chat** if you can: set it as an environment variable in the terminal where the agent runs.

   ```bash
   export KIOSKY_TOKEN='paste-the-token-here'
   ```

   In fish use `set -x KIOSKY_TOKEN 'paste-the-token-here'`.
5. Make sure your computer is on the same network as the tablet.
6. Paste the prompt below into your assistant and fill in the goal.

What the agent **cannot** do over REST, so you do it on the tablet: set the admin PIN, change **Allow remote unlock** or **Allow remote security changes**, enter the Home Assistant token, the MQTT password or the Immich API key (secrets are never part of the config), and provision full lock (Device Owner needs `adb`). By default the agent also cannot change the protected settings, such as the MQTT broker address.

> **Warning.** The tablet's API uses plain HTTP and the token controls the tablet. Keep it on your home network, never forward the port to the internet, and rotate the token (**Regenerate**) when you are done if you shared it anywhere you do not control.

## Copy this prompt

```text
You are going to configure an Android kiosk tablet running Kiosky through its local REST API.

First read the Kiosky documentation: https://kiosky.enraio.com/docs/ai-setup.md (follow its
"Steps for the agent" and "Safety rules" exactly), and use https://kiosky.enraio.com/docs/rest-api.md
and https://kiosky.enraio.com/llms-full.txt as the reference. Do not guess setting names, command
names or config paths; take them from those pages or from GET /api/config.

Tablet address: <TABLET_IP or "find it with mDNS">   Port: 2323
The API token is in the environment variable KIOSKY_TOKEN. Never print it, never write it into a
file, log, chat message or Home Assistant YAML (use secrets), and never send it anywhere except the
tablet's Authorization header.

My goal: <describe what you want, for example:
  - show my Home Assistant dashboards "Home" and "Energy", rotating every 45 seconds
  - dim at 2 minutes, show a clock after 5, screen off at 10
  - turn the screen off from 22:30 to 06:30
  - create a Home Assistant automation that shows camera.front_door on the tablet when someone is at the door>

Rules: discover and read before you change anything; save a backup of the current config; always
use PATCH /api/config?dryRun=true before saving (PATCH changes only the fields you send, PUT
replaces everything); ask me before any sensitive command (reboot, restart_app, clear_cache, kiosk_pause,
launch_app, exit_app_mode), before touching protected settings or the lock, and before changing
anything that needs me at the tablet. Tell me what you changed when you finish, and how to roll it back.
```

## Steps for the agent

Follow these in order. Stop and ask the human whenever a step says so. `TABLET` is the tablet's `host:port`.

### 1. Find the tablet

If the human gave an IP address, use it with port 2323 unless they said otherwise. Otherwise discover it with mDNS. The tablet advertises `_kiosk._tcp` and `_http._tcp` while the REST server runs.

```bash
# macOS
dns-sd -B _kiosk._tcp local
dns-sd -L "<service name>" _kiosk._tcp local      # prints host, port and TXT records

# Linux
avahi-browse -rt _kiosk._tcp
```

Android cannot publish a `.local` host name, so use the resolved IP address and port, not a `.local` name. If mDNS finds nothing, ask for the IP address (**Settings, Device** or **Connections, Remote access** on the tablet).

Confirm it is a Kiosky tablet. This endpoint needs no token:

```bash
curl -s http://TABLET/api/info
# {"app":"Kiosky","name":"Hallway Tablet","id":"hallway_tablet","version":"0.1.0"}
```

Check that `app` is `"Kiosky"`. Note `name`. If the request fails, the REST server may be off: ask the human to switch on **REST API & admin page**. Never scan other hosts or ports looking for it.

### 2. Use the token safely

The token is in the environment variable `KIOSKY_TOKEN`. If it is not set, ask the human to set it; do not ask them to paste it into the chat. Pass it only as a header:

```bash
curl -s -H "Authorization: Bearer $KIOSKY_TOKEN" http://TABLET/api/state
```

- `401` means a wrong or old token. Ask the human to check it. Do not try variations or other tokens.
- `429` means the address is locked out after failed attempts. Stop, wait the number of seconds in the `Retry-After` header, and ask the human before retrying.
- Do not echo the variable, print request headers, or run commands with `-v` or `--trace` that would show the header.

### 3. Read the current state

```bash
curl -s -H "Authorization: Bearer $KIOSKY_TOKEN" http://TABLET/api/state
```

Read `kioskMode` (`none`, `soft`, `device_owner`), `screenStage`, `currentUrl`, `battery` and `network`. Report anything odd to the human before changing it.

### 4. Read the config and keep a backup

```bash
curl -s -H "Authorization: Bearer $KIOSKY_TOKEN" http://TABLET/api/config > kiosky-config.backup.json
```

`kiosky-config.backup.json` is your rollback. It contains no secrets, but it does describe the tablet, so keep it private. Use the exact names in this file (and the [config reference](rest-api.md#config-reference)) for every change.

### 5. Change the config safely

Use `PATCH /api/config` for changes. It deep-merges the partial JSON you send onto the current config: objects merge key by key, and arrays and scalar values replace the current value. Fields you leave out keep their current value. Send only what you intend to change.

```bash
# Example: rotate two dashboards every 45 seconds (arrays replace, so send the whole dashboards list)
cat > kiosky-patch.json <<'JSON'
{
  "browser": {
    "dashboards": [
      {"name": "Home", "url": "http://homeassistant.local:8123/lovelace/0?kiosk"},
      {"name": "Energy", "url": "http://homeassistant.local:8123/energy?kiosk"}
    ],
    "rotation": {"enabled": true, "intervalSeconds": 45, "pauseSeconds": 60}
  }
}
JSON
```

Rules for the patch:

- Dashboard names must be unique, 1 to 64 characters, and URLs must be `http(s)`.
- `power.night` and `maintenance` times are `HH:mm`. Weekdays are 1 (Monday) to 7 (Sunday).
- Do not touch `remote`. You cannot change it over REST.
- The protected paths are `kiosk`, `remote`, `server`, `camera.stream`, `homeAssistant.baseUrl`, `browser.injections`, `browser.allowedHosts`, `browser.bridgeOrigins`, `browser.mediaOrigins`, `mqtt.host`, `mqtt.port`, `mqtt.tls`, `mqtt.username`, `mqtt.publishNetworkInfo`. Changing one returns `403 protected`. Do **not** work around this. Tell the human which setting you need and why, and ask them to change it on the tablet (**Settings**) or to turn on **Allow remote security changes** themselves if they accept the risk.

### 6. Dry run, then save

```bash
# validate only, nothing is saved
curl -s -X PATCH "http://TABLET/api/config?dryRun=true" \
  -H "Authorization: Bearer $KIOSKY_TOKEN" -H "Content-Type: application/json" \
  --data @kiosky-patch.json
# {"ok":true,"saved":false}
```

Read the result:

- `200 {"ok":true,"saved":false}`: valid. Tell the human what will change, get a go-ahead for anything beyond what they asked for, then save.
- `422`: read `errors[].path` and `errors[].message`, fix the patch and dry-run again. A path of `$` means the body was not a JSON object.
- `403 protected`: see the rule above. Nothing was saved.

Then save, and verify:

```bash
curl -s -X PATCH http://TABLET/api/config \
  -H "Authorization: Bearer $KIOSKY_TOKEN" -H "Content-Type: application/json" \
  --data @kiosky-patch.json
# {"ok":true,"saved":true}

curl -s -H "Authorization: Bearer $KIOSKY_TOKEN" http://TABLET/api/config | jq -S . > after.json
diff <(jq -S . kiosky-config.backup.json) after.json    # shows exactly what changed
```

To roll back, `PUT` the backup (this replaces everything with the backup):

```bash
curl -s -X PUT http://TABLET/api/config \
  -H "Authorization: Bearer $KIOSKY_TOKEN" -H "Content-Type: application/json" \
  --data @kiosky-config.backup.json
```

### 7. Send commands to test

Commands return `202 {"ok":true}` when queued. Start with harmless ones:

```bash
curl -s -X POST http://TABLET/api/command \
  -H "Authorization: Bearer $KIOSKY_TOKEN" -H "Content-Type: application/json" \
  -d '{"command":"toast","args":{"text":"Configured by an assistant","duration":6}}'
```

Other useful, benign commands: `reload`, `dashboard` (`{"name":"Energy"}`), `screen` (`{"state":"on"}`), `brightness` (`{"level":128}`), `screensaver`, `load_url` (host must be allowed), `popup`, `dismiss_popup`, `tts`, `volume`. The full list with arguments is in the [REST API reference](rest-api.md#commands). To see what is on screen, fetch `GET /api/screenshot` to a local file (a PNG).

Sensitive commands (`reboot`, `restart_app`, `clear_cache`, `kiosk_pause`, `kiosk_lock` with `off`, `launch_app`, `exit_app_mode`) are refused with `403` unless the human enabled **Allow remote unlock**. **Ask the human before sending any of them,** and never ask them to turn the switch on just to make your job easier.

### 8. Create Home Assistant automations

Only do this if the human wants it and has given you a way to edit Home Assistant (their own tooling, a Home Assistant MCP server, or a file they gave you access to). Do not ask for or store the Home Assistant token in the Kiosky config.

1. **Find the device id.** The device id is the lower-case slug of the device name with `_` between words, the same as `id` from `/api/info` and the mDNS `id` record, for example `Hallway Tablet` is `hallway_tablet` (the same value as `id` from `/api/info`). Topics are `kiosk/<id>/cmd/<command>`.
2. **Check MQTT is connected.** The tablet's MQTT chip must say **Connected** and Home Assistant discovery must be on. If `mqtt.enabled` is false, MQTT host, port, TLS and username are protected, and the password is a secret, so the human must enter them on the tablet under **Settings, Connections, MQTT**. See [Home Assistant integration](home-assistant.md#set-up-mqtt).
3. **Look up real entity ids** in Home Assistant instead of guessing them (the tablet creates entities such as `select.<name>_dashboard` and `binary_sensor.<name>_tamper`; the exact id depends on the device name).
4. **Write the automation** with `mqtt.publish` to the command topic. Example: show a camera when someone is at the door.

   ```yaml
   automation:
     - alias: Hallway tablet shows front door camera
       triggers:
         - trigger: state
           entity_id: binary_sensor.front_door_person
           to: "on"
       actions:
         - action: mqtt.publish
           data:
             topic: kiosk/hallway_tablet/cmd/popup
             payload: >-
               {"camera": "camera.front_door", "timeout": 30, "title": "Front door"}
   ```

   Camera popups need the Home Assistant address and token saved on the tablet under **Dashboard, Home Assistant sign-in**. If they are not, ask the human to add them.
5. **Validate** the Home Assistant configuration (Developer tools, or `check_config`) before reloading automations.
6. **Test** by publishing the same payload yourself with the REST API (`popup` with a `camera` argument), or by triggering the automation once, and ask the human to confirm they see it.
7. **Keep secrets out of YAML.** If an automation uses `rest_command` against the REST API, put the `Bearer <token>` string in `secrets.yaml` and reference it with `!secret`. Prefer MQTT automations, which need no token.

More examples (wake on presence, text to speech, switch dashboard, tamper alert) are on the [Home Assistant integration](home-assistant.md#example-automations) page.

### 9. Report

Tell the human, briefly: what you found, what you changed (a diff), what you tested and what worked, which things they still need to do on the tablet, and how to roll back (`PUT` the backup file). Delete temporary files that hold anything private. Do not include the token in the report.

## Safety rules

These apply to the agent for the whole session.

1. **Never expose port 2323 to the internet.** Do not create port forwards, tunnels, reverse proxies or cloud relays to the tablet. Use the REST API only from the local network.
2. **Never print or paste the token.** Not in the chat, not in logs, not in `curl -v` output, not in command lines that get recorded, not in files you commit, not in gists, issues, pull requests, tickets, screenshots or any other public or shared place. Pass it only in the `Authorization` header, from the environment variable.
3. **Ask before enabling remote unlock or security changes.** **Allow remote unlock & app control** and **Allow remote security changes** can only be changed on the tablet, by the person standing at it. Explain what each one allows (see [Security](security.md#remote-control-policy)) and let them decide. Do not suggest them as a shortcut.
4. **Ask before every sensitive or disruptive action:** reboot, restart, clear cache, pausing the lock, opening other apps, leaving single-app mode, turning the camera, microphone or face detection on, and regenerating the API token (it locks out every other client).
5. **Read first, then dry-run, then save.** Keep a backup. Use `PATCH` for changes. `PUT` replaces the whole config, so use it only to restore the backup.
6. **Respect `403 protected`, `403` policy refusals and `409`.** Do not look for another way around them.
7. **Respect rate limits.** After a `401` or `429`, stop. Do not retry in a loop. Never try to guess a token.
8. **Stay on the tablet you were pointed at.** Do not scan the network for other tablets or services.
9. **Keep Home Assistant secrets out of Kiosky and Kiosky secrets out of Home Assistant YAML.** Use `secrets.yaml` or your platform's secret store.
10. **Do not change what you were not asked to.** Mention opportunities (for example, "you could add a night schedule") and let the human choose.
