Guide

Learn how to configure your KeyPad and use AI assistant skills

AI Assistant Skills

For AI Users

Official skill files for Claude, Cursor, and other AI assistants. These are instructions for your AI tool - SinTuch does not run AI on the keypad or in the app.

How to use

  1. Download or copy SKILL.md and examples.md into your assistant's skills folder.
  2. Describe the workflow you want in plain language: what should happen when you press a key and which preset and button to use (for example preset 1 and button 4). Your AI assistant creates the macro and sets it up for you.
---
name: sintuch-keypad
description: >-
  Key Pad / SinTuch — Generate macro template JSON (`program`, blocks with fixed
  `title`/`color`), optional `presets.json` wiring, Templates paths, and Script
  Builder batch programs (`sb_*` → `scripts/comp`). Use when the user mentions
  Key Pad, SinTuch, key_pad_app, keypad macros, macro editor JSON, presets.json,
  Script Builder, or run_script.
---

# Key Pad / SinTuch / key_pad_app Macro Generator

Companion file: `**examples.md**` — macro patterns, preset wiring, and **Script Builder** program samples.

Behavior is defined by the Key Pad app’s **macro editor** and **Script Builder** (how JSON is saved) and its **runtime** (how macro blocks are converted and executed). Script programs compile to **cmd.exe** batch files. No particular source tree is assumed here.

---

## Purpose

Generate **canvas-format macro templates** (JSON with `program` and blocks using `params`, fixed `title` / `color`) for the Key Pad / SinTuch macro editor and hardware executor. Optionally describe `**presets.json`** merges so a preset slot runs a saved macro file.

Also document or hand-author **Script Builder** programs (`sb_*` block types) that compile to `.bat` under `**scripts/comp`**, and how macros invoke those batches via `**run_script**`.

---

## Activation Keywords


| Kind               | Terms & aliases                                                                                                                      |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Product / UI**   | **Key Pad**, **SinTuch**, **Sin Tuch**                                                                                               |
| **Config on disk** | `**key_pad_app`**, `**%APPDATA%\Roaming\key_pad_app**`, `**Templates**`, `**presets.json**`                                          |
| **Task keywords**  | keypad macro, macro blocks, macro editor JSON, template macro, 3×3 button, preset slot, hardware keypad assignment                   |
| **Scripting**      | **Script Builder**, `**scripts/source`**, `**scripts/comp**`, compiled `**.bat**`, `**sb_***` blocks, `**run_script**` `script_path` |


**Treat macro + preset rules as one system** — this skill’s macro schema and `**examples.md`**. Script programs reuse the same `**{ "program": [...] }**` wrapper but **only `sb_*` block types**; do not mix macro executor types into Script Builder JSON.

**Suggested skill blurb:** *Key Pad / SinTuch — Generate macro template JSON (`program`, blocks with fixed `title`/`color`), optional `presets.json` wiring, `Templates` paths, and Script Builder batch programs (`sb_*` → `scripts/comp`). Keywords: Key Pad, SinTuch, key_pad_app, keypad macros, Script Builder.*

---

## When To Use

Activate when the user mentions **Key Pad**, **SinTuch**, **keypad** (this device/app), `**key_pad_app`**, macro **JSON** / **templates** for this app, `**presets.json`** binding, `**Templates**`, **Script Builder**, `**scripts/source`**, `**scripts/comp**`, or compiled **batch** / `**sb_`** blocks.

**End-user prompt checklist** (ask them to specify where helpful):

1. **Goal** — what the macro should do on Windows.
2. **Output** — one JSON object with `program` unless multiple files are explicitly needed.
3. **Constraints** — paths, window titles, coordinates, repeat counts, exact vs partial window match.
4. **Reuse** — existing `Foo.json` template → `template` block with `template_name`: `"Foo"` (no `.json`).
5. **Constants** — every block needs schema-accurate `title` and `color`.
6. **Disambiguate “run”** — “open/launch” vs “in terminal” vs “run script block / no terminal” (see **Run vs Open Rules**).
7. **Preset + key** — preset **1–10** and key **1–9** (top-left = 1) if wiring `**presets.json`**.

Encode if-window checks as `**params.condition**` strings (`check_window:…`, `is_focused:…`), never as fake extra children for the condition slot.

---

## Required Output Rules

- Output **valid JSON only** for macro definitions unless the user explicitly asks for explanation without JSON.
- **Root object** must contain `**"program"`** as an array of blocks (unless legacy array-only format is explicitly requested).
- **Every block** MUST include:
  - `**type`**
  - `**params**` (object; may be `{}`)
  - `**title**` — fixed constant for that `type` (see **Fixed Block Type Table**)
  - `**color`** — fixed constant for that `type` (same table)
- **Canonical key order** (matches the macro editor): `**type`** → `**params**` → `**title**` → `**color**` → `**children**` (containers only). Emit JSON objects in this order.
- `**title` and `color` are not customizable** — copy exact strings and hex from the table. Do not localize, rename, or recolor.
- **Never invent unsupported block types.** For **macros**, only types in **Fixed Block Type Table** / macro **Params Reference**. For **Script Builder**, only `**sb_*`** types in **Script Block Type Table**.
- `**children`** allowed **only** on `**if_condition`**, `**repeat**`, `**while**`, with correct `**area**` keys. **Script Builder programs do not use `children`** — flat `**program**` list only.

---

## Response Modes


| Mode            | Behavior                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Default**     | Single fenced JSON object: `{ "program": [ … ] }` only (minimal prose after if needed).                                                                                                                                                                                                                                                                                                                                                                                              |
| **Placeholder** | Use `YOUR_…` / `YOUR_ABSOLUTE_SCRIPT_PATH` / `YOUR_PROJECT_ROOT` etc. when paths unknown; add **one short line** listing what each placeholder replaces.                                                                                                                                                                                                                                                                                                                             |
| **Multi-file**  | When user asks for macro **+** `presets.json` update **or** macro **+** nested template file: emit **each** JSON artifact clearly labeled (e.g. `MyMacro.json`, `CommonSave.json`, `presets.json` merge instructions). Preserve `**__global__`** and unrelated preset data when describing merges. When user asks for a **Script Builder script**: emit **both** `**scripts/source/<Stem>.json`** and `**scripts/comp/<Stem>.bat**` (same `<Stem>`) per **Script deliverable rule**. |


---

## Never Do

- Never invent **block `type`** values not in this skill.
- Never invent or alter `**title**` / `**color**` per block (must match **Fixed Block Type Table** exactly).
- Never emit **invalid JSON** (no trailing commas; escape `\` in Windows paths inside strings).
- Never add `**children`** to blocks other than `**if_condition**`, `**repeat**`, `**while**`.
- Never represent `**if_condition**` window tests as separate JSON children (use `**params.condition**` strings only).
- Never modify `**__global__**`, preset `**icon**` arrays, or unrelated `**buttons**` when patching `**presets.json**` unless explicitly requested.
- Never fabricate `**full_path**` for presets — it must match the real saved macro absolute path under `**Templates**` (or user-provided path).
- Never deliver `**scripts/comp/<Stem>.bat**` without the paired `**scripts/source/<Stem>.json**` (Script Builder format, same stem, same logic) — see **Script deliverable rule**. The user must always be able to **Load** the JSON in Script Builder to read and edit what the batch does.

---

## Invalid Requests

- Do **not** create **fake schema extensions**, nonexistent block fields, or alternate JSON shapes “for convenience.”
- If the user asks for behavior **impossible** with supported blocks (e.g. OCR, arbitrary HTTP without `run_script`/terminal pattern), **state the limitation briefly** and propose the **closest supported composition** (`launch_app`, `run_script`, terminal + `type_text`, etc.).
- Do not silently substitute unrelated apps or paths; use placeholders when unknown.

---

## Universal Intent Mapping

Use for **open-ended** prompts not copied verbatim from `**examples.md`**:

1. **Decompose** the request into ordered steps (open → wait → focus → type → shortcut → branch → loop).
2. **Map steps** to blocks using **Params Reference** and `**examples.md`** by analogy; compose primitives even when no single example matches.
3. Insert `**wait**` between UI transitions (often **0.2–1.5 s**); longer after launches or UAC.
4. **Branches** → `**if_condition`** + `**condition**` strings; **loops** → `**repeat`** / `**while**`.
5. **Ambiguity** → default `**exact_match: false`** / `**condition_exact_match: false**` for partial titles unless user demands exact; use `**YOUR_…**` placeholders and list replacements.
6. **Snap layouts** → use **macro blocks** (`open_folder` → `focus_window` → `press` + `wait`) — **not** batch/PowerShell for snapping. **Robust snap-assist pattern** (battle-tested on Explorer):
  ```
   press win+arrow1  →  wait 0.1s  →  press esc  →  press win+arrow2  →  wait 0.1s  →  press esc
  ```
   **No wait between `esc` and the second arrow** — go straight to the next arrow key. Only **0.1s waits** before each `esc` (after each arrow). Pre-snap: `**open_folder`** → `**wait` 0.7s** → `**focus_window`** (partial title) → `**wait` 0.3s** → snap sequence.
   Corner arrows: top-left = `left` then `up`; top-right = `right` then `up`; bottom-left = `left` then `down`; bottom-right = `right` then `down`. If a heavy window mis-snaps, try **0.2s** before each `esc` only (keep **no wait** between `esc` and the second arrow).
7. **“Run file” / “execute file”** → apply **Run vs Open Rules**; state your assumption in one sentence if still ambiguous.
8. **Preset + button** → compute `**"row,col"`** from button index **1–9**; merge `**presets.json`** per **presets.json Rules**.
9. Prefer `**focus_window`** + short `**wait**` after `**open_folder**` / `**launch_app**` when the next action needs a specific foreground window — especially when another app (e.g. a slow launcher) may steal focus before snap.

---

## Run vs Open Rules

Users confuse **open like double-click** with **execute script**. Use **extension + cues**:


| User intent (words + extension)                                       | Block                                                                                          | Typical cues                                                                                        |
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Open / launch** as Windows would (app, installer, document, `.lnk`) | `**launch_app`**                                                                               | “open”, “start”, “launch”, “double-click”, `.exe` without “in terminal”, Office/PDF/media           |
| **Execute script without a terminal window** (Key Pad subprocess)     | `**run_script`**                                                                               | `.py`, `.bat`, `.ps1`, … **only if** background / no shell; not “show output”, “PowerShell”, “venv” |
| **Run a CLI in a shell**                                              | `**launch_app`** / `**focus_window**` terminal → `**type_text**` CLI → `**press**` `**enter**` | “in terminal”, “cmd/PowerShell”, `**py …**`, cwd, venv, visible output                              |


**Ambiguous phrases** (“run this file”, “execute `foo.py`”, “run the installer”):

1. `**.exe`, `.msi`, `.lnk`, Office/media** → almost always `**launch_app`** (unless explicit headless-from-Key-Pad).
2. **Scripts** without terminal language → `**run_script`** vs `**launch_app**` (double-click `.bat`); **state which you chose**.
3. Always **state assumption** when fuzzy.

### `run_script` vs terminal


| Approach         | Pattern                                                                             | When                                                   |
| ---------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `**run_script`** | One block: `**script_path**`                                                        | Key Pad starts file as subprocess; **no** terminal UI. |
| **Terminal**     | Terminal → `**wait`** → `**focus_window**` → `**type_text**` full CLI → `**enter**` | User would paste into shell; needs cwd/venv/output.    |


**Rule:** Paste-into-terminal → **no `run_script`**. Double-click behavior → `**launch_app**`. Headless script from Key Pad → `**run_script**` may fit.

### Scripts vs macro blocks (window / folder workflows)


| Task                                     | Use                                                                       | Do **not** default to                                            |
| ---------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| Headless export, CLI, compiled batch     | `**run_script`** (Script Builder → `.bat` / `.py`)                        | HID blocks                                                       |
| Open a folder in Explorer                | `**open_folder**` with `**full_path**`                                    | `explorer` in a batch (unless user explicitly wants script-only) |
| Bring a window to front before snap/type | `**focus_window**` (partial `**window_title**`, `**exact_match: false**`) | PowerShell `Activate()` in a batch                               |
| Snap a quarter of the screen             | `**press**` (`meta`+arrows) + `**wait**` + `**esc**` per **Snap layouts** | Snap logic hidden in `.bat`                                      |


**Compose:** `run_script` (heavy work) → `**wait`** (let slow apps finish) → `**open_folder**` → `**focus_window**` → snap `**press**` chain. See `**examples.md**` — **Open Folder And Snap Explorer Top Left**, **Open Folder And Snap Explorer Top Right**, **Export Then Snap Today Folder** (template).

**Editor note:** For `**open_folder`**, prefer `**full_path**` in `**params**` (not only `path`) so the macro editor displays the folder; runtime accepts both.

### Launching common apps (battle-tested patterns)


| Goal                              | Pattern                                                                                                                                                                                                                                                    |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Windows Terminal / PowerShell** | `launch_app` with **full path** to `powershell.exe` (`C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`) is more reliable than `wt`/`powershell` shorthand on machines without those on PATH.                                                     |
| **Plain cmd**                     | `launch_app` with `cmd` (or full path `C:/Windows/System32/cmd.exe`).                                                                                                                                                                                      |
| **Elevated cmd (admin)**          | Use the **Run-dialog elevation pattern** below — `launch_app cmd` does not elevate.                                                                                                                                                                        |
| **Explorer at a specific folder** | Two options: **(a)** `open_folder` block with `full_path` (forward slashes), **OR (b)** Run-dialog: `win+r` → wait → `type_text` path → `enter`. (b) sometimes maps more reliably onto user habit when the macro is composed alongside `cd` / shell input. |


### Admin / UAC elevation pattern

Launching elevated processes can't be done with `launch_app` alone — UAC needs to fire and be confirmed. Canonical sequence:

```
press win+r            ← open Run dialog
wait 0.2s
type_text "cmd"        ← or whatever exe
press ctrl+shift+enter ← request elevation
wait 0.5s              ← let UAC dialog appear
press tab              ← move focus from default to "Yes" group
press tab              ← (Win 11 default UAC: two tabs land on Yes)
press enter            ← confirm
wait 1.0s              ← let elevated process spawn
```

Notes:

- Don't follow this with `focus_window "Administrator"` — the new elevated window is already foreground after UAC accepts.
- Tab count to reach **Yes** depends on UAC layout; `tab` × 2 is the Windows 11 default. If the macro mis-presses, try 1 or 3 tabs.
- The wait after `ctrl+shift+enter` (0.5s) must be long enough for the UAC dialog to render. Slow disks → bump to 1s.

### `type_text` paths vs `full_path` paths

Path slashes differ by context:

- `**full_path` (in `launch_app`, `open_folder`, `run_script`):** use **forward slashes**, single string — `C:/Users/foo/Documents`. Backslashes also work but require JSON escaping.
- **Inside `type_text`** (typing into a shell or Run dialog): use **escaped backslashes** — `cd C:\\Users\\foo\\Documents`. The user is going to see backslashes in their shell exactly as typed.

**CLI in `type_text`:** e.g. `py YOUR_PROJECT_ROOT\\tools\\script.py`, `powershell -NoProfile -File "YOUR_SCRIPT_PATH.ps1"`. Escape `\` for JSON. `**./script.py`** needs correct cwd — use absolute path or prior **`cd` / `Set-Location`** line + Enter.

---

## Execution Rules

- **Templates directory:** `%USERPROFILE%\AppData\Roaming\key_pad_app\Templates\`
- **Macro files:** `<name>.json`
- `**template` block:** `template_name` is **basename only** (no `.json`); loads from **Templates** folder.
- **Runner shape:** expects `**type`** + `**args**`. Editor saves `**type**` + `**params**`. Runtime **maps `params` → `args`** and preserves `**children**` for containers.
- **Template / editor JSON:** always `**params`** + fixed `**title**` / `**color**` per block.
- **Raw execution-only payloads** (unusual): may use `**args`** instead of `**params**`; `**title`/`color**` not required for execution only.
- **Legacy load:** root may be **only** an array of blocks (no `**program`** key); prefer `**program**` wrapper otherwise.
- **Window snap:** `**meta` (alias `win`) + arrow** → `**wait` 0.1s** → `**esc`** → **next arrow immediately** → `**wait` 0.1s** → `**esc`** — see **Universal Intent Mapping** point 6. Precede with `**open_folder`** + `**focus_window**` when snapping Explorer.
- `**repeat`:** body must be non-empty or executor errors (“No blocks specified for repeat action”).
- `**template`:** no circular includes.

---

## Script Builder (compiled `.bat`)

SinTuch’s **Script Builder** is a separate canvas from the **macro** editor. It produces **Windows cmd.exe batch** scripts, not HID/automation sequences.

### Paths (Windows)


| Role                                        | Directory                                                            |
| ------------------------------------------- | -------------------------------------------------------------------- |
| **Source JSON** (saved from Script Builder) | `%APPDATA%\Roaming\key_pad_app\scripts\source\` — file `<stem>.json` |
| **Compiled batch** (written on Save)        | `%APPDATA%\Roaming\key_pad_app\scripts\comp\` — file `<stem>.bat`    |


Saving a script writes **both** the JSON and the `.bat`. The app’s **built-in batch compiler** emits one or more cmd.exe lines per block, plus a standard wrapper (`@echo off`, `setlocal EnableExtensions`, and `exit /b 0`).

### JSON shape

Same top-level object as macros:

```json
{ "program": [ /* script blocks only */ ] }
```

Each block has `**type**`, `**params**`, `**title**`, `**color**` — `**title` / `color` must match the Script Block Type Table** (editor-enforced constants).

### Script Block Type Table


| `type`       | `title` (exact) | `color` (exact) |
| ------------ | --------------- | --------------- |
| `sb_comment` | `Comment`       | `#94a3b8`       |
| `sb_run_cmd` | `Run command`   | `#ff6b6b`       |
| `sb_set_var` | `Set variable`  | `#a78bfa`       |
| `sb_delay`   | `Delay`         | `#4facfe`       |
| `sb_start`   | `Start process` | `#84a98c`       |
| `sb_raw`     | `Raw line`      | `#ffd93d`       |


### Script block params (compiler contract)


| `type`       | `params`                                               | Emitted batch (summary)                                       |
| ------------ | ------------------------------------------------------ | ------------------------------------------------------------- |
| `sb_comment` | `text`                                                 | `REM …`                                                       |
| `sb_set_var` | `name`, `value`                                        | `set "NAME=value"` (sanitized name; cmd quote rules on value) |
| `sb_delay`   | `seconds` (int)                                        | `timeout /t N /nobreak >nul`                                  |
| `sb_run_cmd` | `command`                                              | **First line only**, verbatim                                 |
| `sb_start`   | `start_title`, `executable`, `arguments` (string list) | `start "title" "exe" "arg" …`                                 |
| `sb_raw`     | `text`                                                 | **First line only**, verbatim                                 |


`**sb_run_cmd` vs `sb_raw`:** same emission rules today; use **Run command** for “execute this cmd line” and **Raw line** when you want a literal batch line pasted as-is (mental model only).

**Limitations:** no containers (`if`/`repeat` as macro-style JSON) — express branching with batch syntax inside `**sb_run_cmd`** / `**sb_raw**`. Sub-second waits are not represented in `**sb_delay**` (compiler clamps integer seconds).

### UI integration

- **Load** reads a `**.json`** file from disk (file dialog starts under `**scripts/source**`, but you can pick any path). If the JSON matches this schema, **blocks appear on the canvas** in program order.
- **Save** prompts for a name under `**scripts/source`** and refreshes `**scripts/comp\<stem>.bat**`.
- **Test Run** (Script Builder footer) runs the compiled `**<stem>.bat`** if it exists (save first).
- **Export** can write JSON anywhere; only **Save** updates `**scripts/comp`**.

### Script deliverable rule

When the user asks for a **Script Builder script** (with or without a macro that calls it), deliver **transparently**: every batch must have a matching Script Builder JSON source the user can open in the app.

**Pairing (required):**


| File                             | Role                                                                                                                                                                                                                           |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `**scripts/source/<Stem>.json`** | **Source of truth for editing** — `{ "program": [ … ] }` with `**sb_*` blocks only**, fixed `**title`** / `**color**` per **Script Block Type Table**. User **Load**s this in Script Builder to review commands on the canvas. |
| `**scripts/comp/<Stem>.bat`**    | **What `run_script` executes** — cmd.exe batch. AI **may** generate this file directly so the script runs immediately without an extra Save step.                                                                              |


**Rules:**

1. **Same `<Stem>`** for both files (e.g. `ExportCase.json` + `ExportCase.bat`).
2. **Same logic** — JSON blocks must correspond to the batch lines (`sb_comment` → `REM`, `sb_run_cmd` → command line, `sb_delay` → `timeout`, etc.). No hidden commands in `.bat` that are not represented in the JSON.
3. **Order does not matter** — AI may write `.bat` first or JSON first, but **both must appear in the same response** (label each file clearly in **Multi-file** mode).
4. **Never deliver `.bat` alone** — without the paired `**scripts/source/<Stem>.json`**.
5. **JSON alone is allowed** only if you tell the user to **Save** in Script Builder once to create `**scripts/comp/<Stem>.bat`** before first `**run_script**` use.
6. Map each meaningful batch line to `**sb_run_cmd**`, `**sb_raw**`, `**sb_comment**`, `**sb_delay**`, `**sb_set_var**`, or `**sb_start**` — do not dump opaque batch as a single block unless one line truly is one command.

**User workflow (recommended):** save both files → Script Builder → **Load** the JSON → review blocks → **Save** (refreshes `.bat` if they edited). User may also run the AI-provided `.bat` directly via `**run_script`** when paths match.

**Runtime note:** `run_script` executes the `**.bat`**, not the JSON. JSON is for **transparency and editing** in Script Builder; `.bat` is for **execution**.

### JSON from an LLM (skill-assisted)

An assistant that follows this skill can output **ready-to-load** Script Builder JSON: same `{ "program": [ … ] }` shape, only `**sb_*`** types, and `**title` / `color**` copied from **Script Block Type Table**.

**What the user does:** paste or save that JSON as a **UTF-8** `.json` file → open **Script Builder** in Key Pad → **Load** → choose the file → blocks render for reading and editing → **Save** when satisfied (writes `**scripts/source`** copy and compiles `**scripts/comp\<stem>.bat**`).

The LLM does **not** need the app to “draw” blocks: the **app** parses JSON on **Load**. The LLM only needs the documented schema.

### Macro hook: `run_script`

The macro block `**run_script`** / `**script_path**` runs a file **as a subprocess from Key Pad** (no terminal UI). Point `**script_path`** at the absolute path of a compiled batch, e.g.  
`%USERPROFILE%\AppData\Roaming\key_pad_app\scripts\comp\MyScript.bat`  
(expanded to a real absolute path in JSON). The macro editor’s **Run Script** file picker **defaults to `scripts/comp`** so compiled batches are easy to pick.

See `**examples.md**` — **Script Builder program (minimal)** and **Run External Script** (with `scripts/comp` note).

---

## Container Rules

- **Root:** `**program`** is ordered siblings (top → bottom execution).
- **Containers with `children`:** only `**if_condition`**, `**repeat**`, `**while**`. Nesting allowed.

`**children` item shape:**

```json
{ "area": "<area_name>", "blocks": [] }
```

Replace `**blocks**` with full block objects (`type`, `params`, `title`, `color`, …).


| Parent             | `area` values                                                                                              |
| ------------------ | ---------------------------------------------------------------------------------------------------------- |
| `**if_condition**` | `**then**`, `**else**` — each area at most once with non-empty `**blocks**` if used; omit unused branches. |
| `**repeat**`       | `**repeat**`                                                                                               |
| `**while**`        | `**while**` — toggle/stop semantics on hardware; editor test-run may run body once.                        |


**If-condition:** Window existence/focus is **not** nested JSON under `**if_condition`**. Use `**params.condition**` + `**condition_exact_match**` (see **Full Schema Reference** — condition grammar).

### Container skeletons (required `title` / `color`)

`**if_condition`:**

```json
{
  "type": "if_condition",
  "params": {
    "condition": "<string>",
    "condition_exact_match": false
  },
  "title": "If Condition",
  "color": "#a78bfa",
  "children": [
    {
      "area": "then",
      "blocks": []
    },
    {
      "area": "else",
      "blocks": []
    }
  ]
}
```

`**repeat`:**

```json
{
  "type": "repeat",
  "params": {
    "times": 3
  },
  "title": "Repeat",
  "color": "#a78bfa",
  "children": [
    {
      "area": "repeat",
      "blocks": []
    }
  ]
}
```

Executor also accepts `**count**` as alias for `**times**` (in `**args**`).

`**while`:**

```json
{
  "type": "while",
  "params": {},
  "title": "While toggled",
  "color": "#a78bfa",
  "children": [
    {
      "area": "while",
      "blocks": []
    }
  ]
}
```

---

## presets.json Rules

- **Path (Windows):** `%APPDATA%\Roaming\key_pad_app\presets.json` — filename `**presets.json`** (lowercase); “presets.JSON” means the same file.
- **Top-level:** keys `**"1"` … `"10"`** (presets). Optional `**"__global__"**` — **preserve** when editing unless user asks to change global theme/colors.
- **Each preset:** `**name`**, `**icon**` (large array — do not wipe when patching one button), `**p_color**`, `**buttons**` map.

### Grid keys (`buttons`)

**Formula** for physical key **B** (1–9, top-left = 1):  
`row = (B - 1) // 3`, `col = (B - 1) % 3`, key `**"{row},{col}"`**.


| Button # | Key                     |
| -------- | ----------------------- |
| 1–3      | `"0,0"` `"0,1"` `"0,2"` |
| 4–6      | `"1,0"` `"1,1"` `"1,2"` |
| 7–9      | `"2,0"` `"2,1"` `"2,2"` |


### Macro slot payload

```json
{
  "text": "SHORT LABEL ON KEY",
  "type": "macro",
  "full_path": "ABSOLUTE_PATH_TO_MACRO_FILE.json"
}
```

- `**full_path`:** absolute path to macro JSON (typically `**...\key_pad_app\Templates\YourMacro.json`**). Runtime loads `**program**` or legacy list from that file.
- `**text`:** label on the key.

### When user says preset **P**, button **B**

1. Emit macro JSON to `**Templates\….json`** (canvas format).
2. Give exact `**full_path**` for JSON (escaped for JSON).
3. **Merge:** read `**presets.json`** → under `**presets[str(P)]**` ensure `**buttons**` → set `**buttons["row,col"]**` → write back; keep `**__global__**`, other presets, other `**buttons**`, `**icon**`, `**p_color**`, `**name**` unchanged unless requested.
4. **Risk:** UI save may overwrite file edits — prefer app **closed** or reload after edit.

---

## Fixed Block Type Table


| `type`         | `title` (exact) | `color` (exact) |
| -------------- | --------------- | --------------- |
| `click`        | `Click`         | `#ff6b6b`       |
| `mouse_select` | `Mouse Drag`    | `#ff6b6b`       |
| `press`        | `Press`         | `#ff6b6b`       |
| `type_text`    | `Type Text`     | `#ff6b6b`       |
| `launch_app`   | `Launch App`    | `#ff6b6b`       |
| `open_folder`  | `Open Folder`   | `#ff6b6b`       |
| `focus_window` | `Focus Window`  | `#6bcf7f`       |
| `check_window` | `Check Window`  | `#6bcf7f`       |
| `is_focused`   | `Is Focused`    | `#6bcf7f`       |
| `if_condition` | `If Condition`  | `#a78bfa`       |
| `repeat`       | `Repeat`        | `#a78bfa`       |
| `while`        | `While toggled` | `#a78bfa`       |
| `wait`         | `Wait`          | `#4facfe`       |
| `run_script`   | `Run Script`    | `#ffd93d`       |
| `template`     | `Template`      | `#ff8e53`       |


---

## Params Reference

Leaf blocks: no `**children`** (ignored if present).


| `type`         | `params` keys                                                                                                                                          | Notes                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| `click`        | `x`, `y` (integers), `click_type` (`Left Click` / `Right Click` / `Middle Click`), optional `hid_between`, `hid_after`, optional `duration` (fallback) | Screen coordinates.                                        |
| `mouse_select` | `start_x`, `start_y`, `end_x`, `end_y`, `select_type` (`Left Drag` / `Right Drag` / `Middle Drag`), optional `hid_between`, `hid_after`                |                                                            |
| `press`        | `combo` preferred (`ctrl+c`, `meta+shift+s`); or `key`, or `keys` (list). Optional `hid_between`, `hid_after`.                                         |                                                            |
| `type_text`    | `text`; optional `hid_between`, `hid_after`                                                                                                            | HID may skip unsupported chars.                            |
| `wait`         | `seconds` (editor) or `duration` (runtime alias)                                                                                                       | Seconds.                                                   |
| `launch_app`   | `path` or `full_path`                                                                                                                                  |                                                            |
| `open_folder`  | `path` or `full_path`                                                                                                                                  | Prefer `**full_path**` in saved JSON (editor displays it). |
| `focus_window` | `window_title`, optional `exact_match` (default **true** if omitted in executor)                                                                       |                                                            |
| `check_window` | `window_title`, optional `exact_match` (default **true**)                                                                                              | As action; in `**if`**, use `**condition**` string.        |
| `is_focused`   | `window_title`, optional `exact_match` (default **true**)                                                                                              |                                                            |
| `run_script`   | `script_path`                                                                                                                                          | Async `.py`, `.bat`, `.ps1`, `.exe`, etc.                  |
| `template`     | `template_name`                                                                                                                                        | Basename only; loads from **Templates**.                   |


---

## Examples Reference

Full JSON patterns live in `**examples.md`**. Use them as the pattern library:


| Example                                     | Topics                                                                       |
| ------------------------------------------- | ---------------------------------------------------------------------------- |
| Delay Then Shortcut                         | `wait`, `press`                                                              |
| Type Text And Confirm                       | `type_text`, `enter`                                                         |
| Click And Drag                              | `click`, `mouse_select`                                                      |
| Apps And Folders                            | `launch_app`, `open_folder`, `%USERNAME%` path note                          |
| Focus If Window Exists                      | `if_condition`, `check_window`, `focus_window`, `launch_app`                 |
| Only When Focused                           | `if_condition`, `is_focused`                                                 |
| Repeat Loop                                 | `repeat`, `children` area `repeat`                                           |
| Nested Repeat In If                         | nested containers                                                            |
| Run External Script                         | `run_script`, headless                                                       |
| Template Two-File                           | `template`, second JSON file                                                 |
| While Toggle Body                           | `while`, toggle semantics note                                               |
| While Drag Select And Click                 | `while`, `mouse_select`, `click`, nested `**area**` `while`                  |
| Release Workflow                            | UAC tab/enter, snap, folder, F5, dual terminals, `type_text` vs `run_script` |
| Open Folder And Snap Explorer Top Left      | `open_folder`, `focus_window`, snap (corrected timing)                       |
| Open Folder And Snap Explorer Top Right     | same pattern, top-right arrows                                               |
| Open Folder And Snap Explorer Bottom Left   | `open_folder`, `focus_window`, snap (corrected timing)                       |
| Export Then Snap Today Folder               | `run_script` + `template` (dated open/focus/snap macro blocks)               |
| Terminal Run Script Typed                   | `launch_app`, `focus_window`, `type_text`, `py` path                         |
| Wire Macro Preset Button                    | `presets.json` merge, formula for `row,col`                                  |
| **Schema parity:** Sequence Wait Type Enter | minimal chain (same as historical schema runnable example)                   |
| **Schema parity:** If Else Notepad Window   | window branch sample                                                         |
| **Schema parity:** Repeat Click Wait        | loop body click + wait                                                       |
| **Script Builder program (minimal)**        | `sb_*` types, `title`/`color` table, compile → `.bat`                        |
| **Run External Script**                     | `run_script`, `**scripts/comp`** path note                                   |


---

## Full Schema Reference

### Canvas block object fields

**Preferred property order:** `**type`**, `**params**`, `**title**`, `**color**`, `**children**` (when present).


| Field      | Required       | Meaning                                             |
| ---------- | -------------- | --------------------------------------------------- |
| `type`     | Yes            | Block kind string.                                  |
| `params`   | Yes            | Arguments object (may `{}`).                        |
| `title`    | Yes            | Must match **Fixed Block Type Table** for `type`.   |
| `color`    | Yes            | Must match **Fixed Block Type Table** for `type`.   |
| `children` | Container only | Only `**if_condition`**, `**repeat**`, `**while**`. |


After runtime conversion: `{ "type": "…", "args": { … }, "children": … }` — `**title`/`color**` not used by executor.

### Root JSON shapes

**Preferred:**

```json
{
  "program": []
}
```

**Legacy:** root may be a bare array of blocks.

### `if_condition`: condition grammar

Stored in `**params.condition`**.


| Pattern                                             | Meaning                                                  |
| --------------------------------------------------- | -------------------------------------------------------- |
| `check_window:<window_title>`                       | Window exists; matching via `**condition_exact_match**`. |
| `is_focused:<window_title>`                         | Window is foreground.                                    |
| `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off` | Booleans.                                                |
| `$variableName`                                     | Runtime variable; missing → false.                       |
| Other non-empty string                              | Truthy if non-empty after strip.                         |


`**condition_exact_match`:** boolean in `**params`**; if omitted in if-branch evaluation, defaults `**false**`.

**Standalone** `**check_window`**, `**is_focused**`, `**focus_window`:** use `**exact_match`** in `**params**`; executor defaults `**true**` when omitted — **stricter** than if-condition default. Prefer setting explicitly.

### Authoring checklist

1. Use `**"program": [...]`** unless legacy array-only is intended.
2. Every block: `**type**`, `**params**`, `**title**`, `**color**` — exact table match; prefer that **property order** in JSON (then `**children`** on containers).
3. Template files use `**params**`; runtime maps to `**args**`.
4. Only `**if_condition**`, `**repeat**`, `**while**` have `**children**`; each child needs `**area**` + `**blocks**`.
5. `**template**`: stem name only; no circular references.
6. `**repeat**`: non-empty `**children**` body required.
7. Preset **P** + button **B`:** merge `**presets.json`** per **presets.json Rules**; preserve **`global`**, **`icon`**, unrelated **`buttons`**.

### Implementation note

Authoritative behavior lives in the Key Pad application sources: macro canvas serialization, canvas→execution conversion, per-type executors, and **Script Builder** save/compile. This skill stays **path-agnostic** for sharing except for the **standard AppData layout** in **Script Builder (compiled `.bat`)**.