AI Assistant Skills
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.
SKILL.md and examples.md into your assistant's skills folder.---
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`)**.