bloby-bot 0.54.11 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,292 +1,276 @@
1
1
  ---
2
2
  name: mac
3
- description: "Morphy native macOS companion. Activates on the [Mac] tag. Output is a concise spoken reply (TTS); optionally accompany it with a <notch_html>…</notch_html> visual card rendered inside the MacBook notch (383×147pt, transparent over black). Frequent snippets are cached in workspace/skills/mac/frequentSnippets/ for instant re-use."
3
+ description: "Morphy native macOS companion. Activates on the [Mac] tag. You reply with a concise spoken line (TTS) and optionally drive the Mac's action registry — one <mac_actions> JSON array that can show a notch card, point the mascot at the screen, or spotlight a control. Custom cards use <notch_html>. The same registry works proactively (PULSE/cron) wrapped in <mac_push>. Card presets + schemas: presets/PRESETS.md. Reusable custom cards: frequentSnippets/."
4
4
  ---
5
5
 
6
- # Mac (Morphy notch)
6
+ # Mac (Morphy companion)
7
7
 
8
8
  ## What This Is
9
9
 
10
- A channel for replying to your human **on their Mac**, through the **Morphy companion app** that lives in the MacBook notch. You speak a short reply (TTS) and *optionally* push a small HTML+CSS card into the notch — same beat as the audio. No pull, no schedule, no state to maintain. Pure output channel.
10
+ A channel for reaching your human **on their Mac**, through the **Morphy companion app** that lives in the menu bar + the MacBook notch. Two things happen per turn:
11
11
 
12
- The notch's bottom slot is rendered with a sandboxed `WKWebView`. You're not building a webpage; you're hand-rolling a single ~9.4 cm² glance card.
12
+ 1. **You speak** your concise reply is read aloud (ElevenLabs TTS).
13
+ 2. **You optionally drive the Mac** — through one **action registry**: a `<mac_actions>` block holding a JSON array of actions. An action can render a **card** in the notch, **point** the mascot at something on screen, or **spotlight** a control. (Custom hand-written HTML cards use the raw `<notch_html>` tag — see below.)
14
+
15
+ The registry is **extensible**: today it's `card`, `point`, `spotlight`; more verbs arrive over time. You drive it the same way whether the human just talked to you (reply) or you're reaching out on your own (proactive push).
13
16
 
14
17
  ---
15
18
 
16
19
  ## When To Use This Skill
17
20
 
18
- Activate when the **user message starts with `[Mac]`**. Don't apply it to other inbound traffic (WhatsApp, Alexa, web chat). Specifically:
21
+ Activate when the **user message starts with `[Mac]`**. Don't apply it to other inbound traffic (WhatsApp, Alexa, web chat).
19
22
 
20
23
  - `[Mac] what's on my calendar today?` → activate
21
- - `[Mac] what time is it in Tokyo?` → activate
24
+ - `[Mac] where do I cancel this subscription?` → activate (point/spotlight at it)
22
25
  - `what's on my calendar today?` (no tag) → ignore this skill, reply as usual
23
26
 
24
- The tag is injected by the Morphy app itself when the human pushes-to-talk through Morphy, so by the time you see `[Mac]` it means **your reply will be spoken back at them**. Optimize for the ear, supplement with the eye.
27
+ The tag is injected by the Morphy app when the human pushes-to-talk, **and every `[Mac]` turn carries a screenshot of each display** so you can *see* their screen and reference exact pixels on it. Optimize for the ear, supplement with the eye, and act on the screen when it helps.
25
28
 
26
29
  ---
27
30
 
28
- ## Two ways to put a visual in the notch
31
+ ## The action registry `<mac_actions>`
32
+
33
+ Your reply has two parts: **spoken prose** (plain text, read aloud) and an optional **`<mac_actions>` block** — a JSON array of actions the Mac runs. The Mac strips the block before TTS, so **it is never spoken**.
29
34
 
30
- There are **two** ways to render a card. Reach for them in this order:
35
+ ```
36
+ Here's your day, Bruno.
37
+ <mac_actions>
38
+ [
39
+ { "type": "card", "preset": "calendar", "data": { "weekday": "Thu", "date": "May 28", "events": [ { "time": "10:00", "title": "Stand-up" } ] } }
40
+ ]
41
+ </mac_actions>
42
+ ```
31
43
 
32
- 1. **Preset (preferred).** Morphy ships a library of beautiful, pre-built card
33
- renderers (`email`, `calendar`, `list`, `text`, `weather`, `ticker`, `stat`,
34
- `info`, `comparison`). You send only **structured data** — never CSS — and
35
- Morphy lays it out perfectly, on-brand, with scrolling handled for you. It's
36
- the fast, pretty, low-token path. **Full data schemas + examples:
37
- [`presets/PRESETS.md`](presets/PRESETS.md).**
44
+ Rules:
38
45
 
39
- ```
40
- <notch_card type="email">
41
- { "from": "Alex Chen", "subject": "Migration plan", "time": "2:14 PM",
42
- "body": "Can we move the cutover to Tuesday?\n\nStaging looked clean." }
43
- </notch_card>
44
- ```
46
+ - **One `<mac_actions>` block per reply.** Put it after your spoken sentence.
47
+ - It's a **JSON array** — you can include **several actions** and they run **in order** (e.g. spotlight a control *and* point at it).
48
+ - Each element is a flat object with a `"type"` and that action's fields.
49
+ - If you have nothing to show or do, send **no block** — just speak.
45
50
 
46
- 2. **Custom (escape hatch).** When no preset fits the shape of the answer,
47
- hand-write the whole card in `<notch_html>…</notch_html>` (rules below). Cards
48
- you hand-build and reuse get saved to `frequentSnippets/` so next time is
49
- copy-fill-send. If a custom card gets requested a lot, tell Bruno — it's a
50
- candidate to become a real shipped preset.
51
+ ### The action types
51
52
 
52
- **Check for a preset first.** Only drop to custom HTML when the data genuinely
53
- doesn't fit one of the presets.
53
+ | `type` | What the Mac does | Fields |
54
+ |---|---|---|
55
+ | `card` | Renders a card in the notch (a preset from the library). | `{ "preset": "<name>", "data": { … } }` |
56
+ | `point` | The mascot flies across the screen and points at a spot, with a label bubble. | `{ "x", "y", "label"?, "screen"? }` |
57
+ | `spotlight` | Dims the display and opens a soft glowing hole over a spot, isolating one control. | `{ "x", "y", "r"?, "label"?, "screen"? }` |
54
58
 
55
- > **Long prose / "read me this" / a summary / an explanation use the `text`
56
- > preset.** Do NOT dump raw paragraphs into `<notch_html>` — that tag is *HTML*,
57
- > not a text box. Bare text there renders unstyled, edge-to-edge, with no padding.
58
- > The `text` preset gives you a title, proper margins, and a scrollable body for
59
- > free: `<notch_card type="text">{ "title": "…", "body": "…long text with \n\n…" }</notch_card>`.
60
- > `<notch_html>` is only for a genuinely custom *visual layout* you hand-build with
61
- > real markup and inline styles — never as a dumping ground for plain text.
59
+ > **Adding capabilities:** new verbs (open an app, run a shortcut, click a button…) will appear here as new `type`s over time. If you try a `type` the app doesn't know yet, it's safely ignored — so only use the types documented above.
62
60
 
63
- ## Output Format
61
+ ---
64
62
 
65
- Your full reply lives inside the conversation; Morphy will:
63
+ ## The `card` action (notch cards)
66
64
 
67
- 1. Strip any `<notch_card …>…</notch_card>` **and** `<notch_html>…</notch_html>`
68
- block before TTS — neither is **ever** spoken.
69
- 2. Send the remaining text to ElevenLabs and play it through the Mac.
70
- 3. Render the card (preset → Morphy's renderer; custom → your HTML) and auto-open
71
- the notch downward **at the same moment** the audio starts. Visual + audio land
72
- together — that's the whole point.
65
+ A card is a small glance-visual in the notch's bottom slot — **383 × 147 pt, transparent over black**. There are two ways to make one; reach for them in this order:
73
66
 
74
- So a reply has up to two parts a spoken sentence and **one** card block (either
75
- a `<notch_card>` preset or a `<notch_html>` custom card, not both):
67
+ ### 1. Preset (preferred)`card` action
68
+
69
+ Morphy ships pre-built, on-brand renderers: **`email`, `calendar`, `list`, `text`, `weather`, `ticker`, `stat`, `info`, `comparison`**. You send only **structured data** — never CSS — and Morphy lays it out perfectly, scrolling handled. **Full data schemas + examples: [`presets/PRESETS.md`](presets/PRESETS.md).**
76
70
 
77
71
  ```
78
- <concise spoken sentence>
79
- <notch_card type="…">{ …data… }</notch_card>
72
+ Here it is, Bruno.
73
+ <mac_actions>
74
+ [ { "type": "card", "preset": "email", "data": { "from": "Alex Chen", "subject": "Migration plan", "time": "2:14 PM", "body": "Can we move the cutover to Tuesday?" } } ]
75
+ </mac_actions>
80
76
  ```
81
77
 
82
- ### Spoken text rules
78
+ > **Long prose / "read me this" / a summary → use the `text` preset**, not custom HTML:
79
+ > `{ "type": "card", "preset": "text", "data": { "title": "…", "body": "…long text with \n\n…" } }`. It gives you a title, margins, and a scrollable body for free.
83
80
 
84
- - **One or two sentences max.** It's audio, not prose. The human is mid-task when this plays don't make them stand still for a paragraph.
85
- - **No markdown, no bullet lists, no enumerations.** TTS reads symbols literally and it sounds awful.
86
- - **Refer the human by name** if you know it ("Here's your calendar for today, Bruno.") — sounds personal, doesn't add length.
87
- - **Acknowledge the card when you send one.** Otherwise the visual feels disconnected from the voice. "Here it is.", "I put the details up top.", "Tap to glance.".
81
+ ### 2. Customraw `<notch_html>` (escape hatch)
88
82
 
89
- ### 🚫 The #1 mistake: speaking the card content out loud
83
+ When no preset fits, hand-write the whole card in a **`<notch_html>…</notch_html>`** tag (separate from `<mac_actions>`). Use the **raw tag, not a JSON string** — that's deliberate: you write real markup with no escaping.
90
84
 
91
- **This is the single most common failure mode and it ruins the UX.** If your card contains a list, a calendar, an email digest, news headlines, search results — *anything structured* — your spoken text **must NOT re-read those items**. The human is already looking at them. Reading them aloud doubles the time-to-information and makes Morphy feel broken.
85
+ ```
86
+ Pinned it up top, Bruno.
87
+ <notch_html>
88
+ <div style="padding:12px 16px;color:#fff;font-family:-apple-system">…your layout…</div>
89
+ </notch_html>
90
+ ```
92
91
 
93
- When the card carries the answer, the voice's only job is the **lead-in sentence**and then stop talking.
92
+ Reusable custom cards live in [`frequentSnippets/`](frequentSnippets/) — read the file, fill the `{{placeholders}}`, drop the result inside `<notch_html>`. If a custom card gets asked for a lot, tell Bruno it's a candidate to become a shipped preset.
94
93
 
95
- #### BAD speaks the card back at the human
94
+ **Check for a preset first.** Only drop to `<notch_html>` when the data genuinely doesn't fit one.
96
95
 
97
- > *"Top five AI today, Bruno. Anthropic dropped Claude Opus 4.7 with a one-million-token window. OpenAI is rolling Sora 3 video into ChatGPT for Plus users. Meta open-sourced Llama 4 Scout at 400 billion params. Google DeepMind's Gemini 3 hit number one on the LMSys arena. And Mistral closed a five billion dollar round at a forty billion valuation."*
98
- > ```
99
- > <notch_html>… the same five items rendered as a list …</notch_html>
100
- > ```
96
+ ### The canvas (for custom cards)
101
97
 
102
- ElevenLabs spends 30+ seconds reciting what's already on screen. The human paid for tokens AND TTS minutes to receive identical information twice. Don't do this.
98
+ | Constraint | Value |
99
+ |---|---|
100
+ | **Size** | **383 × 147 pt** (fixed) — about two stacked Spotlight rows. |
101
+ | **Background** | **Transparent over black**. Black is your canvas; use white/light text. |
102
+ | **Color** | White or `rgba(255,255,255,0.x)` tints read better than gray on black. |
103
+ | **Allowed** | HTML, CSS (flexbox, grid, gradients, transitions, animations), unicode/emoji. |
104
+ | **Forbidden** | External resources — `<img src="https://…">`, `<iframe>`, web fonts. The view has **no network**. |
105
+ | **Interactivity** | No clicks/hovers (they do nothing). Long content **scrolls** via trackpad — overflow is fine. |
106
+ | **Type size** | **12–14 px** is the floor on a Retina notch; below that white-on-black smears. |
103
107
 
104
- #### GOOD lead-in only, card carries the detail
108
+ Tips: two-column `display:flex;gap:8px` at ~190 pt/column; a 1px `rgba(255,255,255,0.08)` divider under a header; don't outline the card (the black pill is the frame).
105
109
 
106
- > *"Here are today's top five in AI, Bruno."*
107
- > ```
108
- > <notch_html>… the same five items rendered as a list …</notch_html>
109
- > ```
110
+ ---
110
111
 
111
- Two seconds of speech, the eye picks up the rest, human keeps working.
112
+ ## `point` & `spotlight` (acting on the screen)
112
113
 
113
- #### Same rule, different shapes
114
+ Because every `[Mac]` turn attaches a **screenshot of each display**, you can reference exact pixels and Morphy animates over the *live* screen at the matching spot.
114
115
 
115
- | Question | Speech | Card |
116
- |---|---|---|
117
- | "What's on my calendar today?" | *"Here's your day, Bruno."* | day + events |
118
- | "Read me my unread emails." | *"Three worth a glance, Bruno."* | sender + subject list |
119
- | "Compare Postgres vs SQLite." | *"Quick side-by-side up top, Bruno."* | two-column card |
120
- | "What's the weather?" | *"Pinned the forecast for you, Bruno."* | temp + conditions |
121
- | "What time is it in Tokyo?" | *"It's 8:14 PM in Tokyo."* | **no card** — bare fact, voice is enough |
116
+ - `x`, `y` **pixels measured on the screenshot you were given this turn** (top-left origin). Read the position straight off the image.
117
+ - `screen` *(optional)* — **1-based display index**, matching the order the screenshots were attached (screen 1 = first image). Omit for a single display or to default to the cursor's screen.
118
+ - `label` *(optional)* short on-screen caption ("Send", "Cancel here").
119
+ - `r` *(spotlight only, optional)* hole radius in points (default 90).
122
120
 
123
- The rule is symmetric: if the **voice alone** is the right answer, send **no card**. If the **card** is the answer, send a **short lead-in** in voice. **Never both at full length.**
121
+ `spotlight` + `point` pair beautifully spotlight to kill the clutter, point to name it:
124
122
 
125
- ### Whether to send a card at all
123
+ ```
124
+ The cancel button's bottom-right, Bruno.
125
+ <mac_actions>
126
+ [
127
+ { "type": "spotlight", "x": 1180, "y": 540, "r": 80, "screen": 1 },
128
+ { "type": "point", "x": 1180, "y": 540, "label": "Cancel", "screen": 1 }
129
+ ]
130
+ </mac_actions>
131
+ ```
126
132
 
127
- - **Sometimes useful, sometimes not.** Decide per reply. A time-of-day answer doesn't need a card. A calendar, a list, a comparison, a statusthose benefit from one.
128
- - **Preset first.** If the answer is an email, a list, a calendar, a stat, a comparison, a quote/summary, weather, or a quote — there's almost certainly a preset for it (see [`presets/PRESETS.md`](presets/PRESETS.md)). Send data, not markup.
129
- - **Custom only when nothing fits.** Reach for `<notch_html>` when the shape is genuinely bespoke. Pin reusable custom cards as files in `frequentSnippets/` so you can copy-swap-send instead of regenerating.
130
- - **The card is display-only — but scrollable.** Don't put buttons, links, or "click to expand" — clicks do nothing and read as broken UI. But long content **is scrollable**: the user scrolls `email` / `list` / `calendar` / `text` cards with the trackpad (a thin scrollbar appears), so it's fine to let content overflow.
133
+ **Reply vs proactive.** On a **reply** to a `[Mac]` turn you saw the screenshot, so coordinates are accurate this is the reliable case. In a **proactive `<mac_push>`** these still work (the app maps your coordinate against a fresh capture of the *current* screen), but you didn't see that screen, so only point/spotlight proactively when you genuinely know where the thing is otherwise send a card.
131
134
 
132
135
  ---
133
136
 
134
- ## The Canvas
137
+ ## Proactive pushes (PULSE / cron — you start the conversation)
135
138
 
136
- | Constraint | Value |
137
- |---|---|
138
- | **Width** | **383 points** (fixed) |
139
- | **Height** | **~147 points** (fixed; bottom is inset to clear the pill's rounded corners) |
140
- | **Background** | **Transparent**. Sits directly on a **black** pill. Plan accordingly — black is your canvas. |
141
- | **Font** | System (`-apple-system, BlinkMacSystemFont, system-ui`) is preloaded. Override only if you need a monospaced number or display weight. |
142
- | **Color** | White or light. Use `rgba(255,255,255,0.x)` for tints — opacity tints read better than gray on black. |
143
- | **Allowed** | HTML, CSS (incl. flexbox, grid, gradients, transitions, animations), unicode glyphs / emoji. |
144
- | **Forbidden** | JS that does network or file access, `<img src="https://...">`, `<iframe>`, anything that loads external resources. The view has no network. |
145
- | **Interactivity** | No clicks or hovers — they do nothing. But long content **scrolls** via the trackpad (a thin scrollbar appears), so overflow is fine. |
139
+ You can reach the Mac **without being asked** — during a `<PULSE/>` run or a scheduled cron, when memory says the human wants a proactive Mac update (a trade status, "tell me when new mail lands", a build result, a reminder).
146
140
 
147
- **383 × 147 is small.** Roughly the size of two stacked Spotlight rows. Treat each card as a single coherent idea — date + time, one event, one fact, one comparison. If you can't fit it, paginate via speech ("here's the first, ask 'next' for the rest"), don't shrink the type.
141
+ Opt-in and quiet by design:
148
142
 
149
- ### Space tips
143
+ - **Only push when the human asked for it** (a memory/instruction). A push interrupts with voice + visuals — never speculative.
144
+ - **Wrap the whole Mac payload in `<mac_push>…</mac_push>`.** Inside, write *exactly* a normal reply: a spoken line + an optional `<mac_actions>` block (a `card` is ideal) and/or `<notch_html>`. The supervisor forwards the wrapper's inner content to the Mac as an unsolicited message; the app speaks it and renders it, same as a reply.
150
145
 
151
- - **Two-column grids** with `display: flex; gap: 8px` are very effective at ~190pt per column.
152
- - **A divider line** (`rgba(255,255,255,0.08)`, 1px) under a header separates regions without visually crowding.
153
- - **Tabs / pagination** can be visual-only (a row of dots indicating "1 of 3"); say "next" in the audio and resend a fresh snippet for page 2.
154
- - **Don't outline the card.** The black pill is already the frame.
155
- - **12–14px is the smallest comfortable size** on a Retina notch. Below that, antialiasing makes white text on black smear.
146
+ ```
147
+ <mac_push>
148
+ Your TSLA position is up 2.1% today, Bruno.
149
+ <mac_actions>
150
+ [ { "type": "card", "preset": "stat", "data": { "value": "+2.1%", "label": "TSLA · today" } } ]
151
+ </mac_actions>
152
+ </mac_push>
153
+ ```
156
154
 
157
- ---
155
+ - **`point`/`spotlight` in a push work, but carefully** — the app maps the coordinate against a fresh capture of the current screen, which you haven't seen. Use them only when you truly know the location; otherwise a spoken line + a `card` (or `<notch_html>`) is the safe choice.
156
+ - **Fire-and-forget, online-only.** The push lands **only if the Mac is connected and the human isn't mid-interaction**; otherwise it's silently dropped (not queued). For must-not-miss updates, also emit a `<Message>` block (web/push) — `<mac_push>` and `<Message>` are independent.
157
+ - **Keep the reply discipline** (below): ≤ 2 sentences, no markdown, never read the card aloud. The human didn't ask, so be especially brief.
158
158
 
159
- ## Frequent Snippets
159
+ If the `mac` skill isn't installed, none of this exists — so only emit `<mac_push>` when this skill is active and the human has opted into Mac updates.
160
160
 
161
- `workspace/skills/mac/frequentSnippets/*.html` — pre-built cards. When your human asks something you've answered before, **don't regenerate** the markup. Read the file, replace placeholders, paste into `<notch_html>…</notch_html>`. Saves tokens, lowers latency, lets the visual feel land at the same beat as the voice.
161
+ ---
162
162
 
163
- **Workflow:**
163
+ ## Spoken-text rules
164
164
 
165
- 1. First time the human asks "what's on my calendar today?"generate a card from scratch, show it, ask: *"Want me to save this as a template for next time?"*
166
- 2. If yes, write it to `frequentSnippets/calendar-today.html` with `{{placeholders}}` for the dynamic bits.
167
- 3. Next time the same question comes in, `Read` the file, do a simple string-replace on the placeholders, paste the result into `<notch_html>…</notch_html>`.
165
+ - **One or two sentences max.** It's audio. The human is mid-task don't make them stand still for a paragraph.
166
+ - **No markdown, no bullet lists, no enumerations.** TTS reads symbols literally and it sounds awful.
167
+ - **Refer to the human by name** if you know it personal, costs nothing.
168
+ - **Acknowledge a card/action when you send one** ("Here it is.", "Pinned it up top.", "It's the gear, top-right.") so the visual feels connected to the voice.
169
+ - **Name things, don't narrate coordinates.** *"It's the gear, top-right."* — never *"I'm pointing at 1890 comma 40."*
168
170
 
169
- Use `{{double_curly}}` placeholders so they're easy to grep and unambiguous. Keep file names kebab-cased and intent-named (`calendar-today.html`, `weather-now.html`, `pomodoro-status.html`).
171
+ ### 🚫 The #1 mistake: speaking the card content out loud
170
172
 
171
- Starter snippets in this skill (read them to see the style):
173
+ If your card carries a list, calendar, email digest, headlines — *anything structured* — your spoken text **must NOT re-read those items**. The human is already looking at them. When the card carries the answer, the voice's only job is a short **lead-in**, then stop.
172
174
 
173
- - `frequentSnippets/calendar-today.html` day + date hero, event list, "no events" empty state.
174
- - `frequentSnippets/info-card.html` two-column key/value card.
175
- - `frequentSnippets/single-stat.html` — one big number, one supporting line.
175
+ **❌ BAD:** *"Top five in AI: Anthropic shipped Claude Opus… OpenAI rolled out… Meta open-sourced…"* (30s reciting what's on screen)
176
+ **✓ GOOD:** *"Here are today's top five, Bruno."* + the list card.
176
177
 
177
- You're encouraged to **discuss the snippet design with your human** they see it every day, they'll have opinions on density, accent color, what to lead with. Keep the file in sync with what they tell you. Treat each `.html` as a small product surface.
178
+ The rule is symmetric: if the **voice alone** is the right answer, send **no card**. If the **card** is the answer, send a **short lead-in**. Never both at full length.
179
+
180
+ | Question | Speech | Visual |
181
+ |---|---|---|
182
+ | "What's on my calendar?" | *"Here's your day, Bruno."* | `card` calendar |
183
+ | "Read me my unread emails." | *"Three worth a glance, Bruno."* | `card` list |
184
+ | "Where do I cancel?" | *"Bottom-right, Bruno."* | `spotlight` + `point` |
185
+ | "What time is it in Tokyo?" | *"It's 8:14 PM in Tokyo."* | **nothing** — voice is enough |
178
186
 
179
187
  ---
180
188
 
181
189
  ## Examples
182
190
 
183
- ### Example 1 Calendar (with card)
191
+ ### Reply with a preset card
184
192
 
185
193
  > **Human:** `[Mac] what's on my calendar today?`
186
- > **You (full reply):**
187
194
  > ```
188
- > Here's your day, Bruno. Stand-up at 10, design review at 2, nothing after 4.
189
- > <notch_html>
190
- > <div style="padding:12px 16px;display:flex;flex-direction:column;gap:8px;height:100%;box-sizing:border-box">
191
- > <div style="display:flex;align-items:baseline;gap:8px">
192
- > <div style="font-size:22px;font-weight:700">Thu</div>
193
- > <div style="font-size:13px;opacity:0.55">May 28</div>
194
- > </div>
195
- > <div style="height:1px;background:rgba(255,255,255,0.08)"></div>
196
- > <div style="display:flex;justify-content:space-between;font-size:11px">
197
- > <span style="opacity:0.7">10:00 · Stand-up</span>
198
- > <span style="opacity:0.4">30m</span>
199
- > </div>
200
- > <div style="display:flex;justify-content:space-between;font-size:11px">
201
- > <span style="opacity:0.7">14:00 · Design review</span>
202
- > <span style="opacity:0.4">1h</span>
203
- > </div>
204
- > </div>
205
- > </notch_html>
195
+ > Here's your day, Bruno. Stand-up at 10, design review at 2.
196
+ > <mac_actions>
197
+ > [ { "type": "card", "preset": "calendar", "data": { "weekday": "Thu", "date": "May 28", "events": [ { "time": "10:00", "title": "Stand-up" }, { "time": "14:00", "title": "Design review" } ] } } ]
198
+ > </mac_actions>
206
199
  > ```
207
200
 
208
- Morphy speaks "Here's your day, Bruno…" while the card slides into the notch.
201
+ ### Reply that acts on the screen
202
+
203
+ > **Human:** `[Mac] where do I turn off notifications?`
204
+ > ```
205
+ > It's the bell icon near the top-right, Bruno.
206
+ > <mac_actions>
207
+ > [ { "type": "spotlight", "x": 1840, "y": 64, "r": 70, "screen": 1 },
208
+ > { "type": "point", "x": 1840, "y": 64, "label": "Notifications", "screen": 1 } ]
209
+ > </mac_actions>
210
+ > ```
209
211
 
210
- ### Example 2 — Quick fact (no card)
212
+ ### Reply, bare fact (no visual)
211
213
 
212
214
  > **Human:** `[Mac] what time is it in Tokyo?`
213
- > **You (full reply):**
214
215
  > ```
215
216
  > It's 8:14 PM in Tokyo.
216
217
  > ```
217
218
 
218
- A bare fact doesn't earn screen real estate. Speak it, move on.
219
-
220
- ### Example 3 — Comparison (card with two columns)
219
+ ### Custom card (no preset fits)
221
220
 
222
- > **Human:** `[Mac] which is better for our use case, Postgres or SQLite?`
223
- > **You:**
224
221
  > ```
225
- > For your use case, Bruno, Postgres edges it out for the concurrent writes. Quick side-by-side up top.
222
+ > Quick side-by-side up top, Bruno.
226
223
  > <notch_html>
227
- > <div style="padding:12px 16px;display:flex;gap:10px;height:100%;box-sizing:border-box">
224
+ > <div style="padding:12px 16px;display:flex;gap:10px;height:100%;box-sizing:border-box;color:#fff;font-family:-apple-system">
228
225
  > <div style="flex:1;padding:8px 10px;border-radius:8px;background:rgba(255,255,255,0.05)">
229
- > <div style="font-size:10px;opacity:0.5;text-transform:uppercase;letter-spacing:.5px">Postgres</div>
226
+ > <div style="font-size:10px;opacity:0.5;text-transform:uppercase">Postgres</div>
230
227
  > <div style="font-size:13px;font-weight:700;margin-top:2px">Concurrent ✓</div>
231
- > <div style="font-size:10px;opacity:0.5;margin-top:4px">Heavier setup</div>
232
228
  > </div>
233
229
  > <div style="flex:1;padding:8px 10px;border-radius:8px;background:rgba(255,255,255,0.05)">
234
- > <div style="font-size:10px;opacity:0.5;text-transform:uppercase;letter-spacing:.5px">SQLite</div>
230
+ > <div style="font-size:10px;opacity:0.5;text-transform:uppercase">SQLite</div>
235
231
  > <div style="font-size:13px;font-weight:700;margin-top:2px">Single-writer</div>
236
- > <div style="font-size:10px;opacity:0.5;margin-top:4px">Zero setup</div>
237
232
  > </div>
238
233
  > </div>
239
234
  > </notch_html>
240
235
  > ```
241
236
 
242
- ### Example 4 — Pagination via voice (long list)
237
+ ### Proactive push (PULSE/cron)
243
238
 
244
- > **Human:** `[Mac] read me my unread emails.`
245
- > **You:** *(reply 1)*
246
239
  > ```
247
- > Three of seven worth a glance, Bruno. First: Alex about the migration. Say "next" for the rest.
248
- > <notch_html>
249
- > <div style="padding:10px 14px;display:flex;flex-direction:column;gap:6px;height:100%;box-sizing:border-box">
250
- > <div style="display:flex;justify-content:space-between;align-items:baseline">
251
- > <div style="font-size:13px;font-weight:700">Unread mail</div>
252
- > <div style="font-size:9px;opacity:0.45">1 / 3</div>
253
- > </div>
254
- > <div style="height:1px;background:rgba(255,255,255,0.08)"></div>
255
- > <div style="font-size:11px"><b>Alex Chen</b> · Migration plan</div>
256
- > <div style="font-size:10px;opacity:0.6">"…can we move the cutover to Tue?"</div>
257
- > </div>
258
- > </notch_html>
240
+ > <mac_push>
241
+ > Build's green, Bruno.
242
+ > <mac_actions>
243
+ > [ { "type": "card", "preset": "stat", "data": { "value": "PASS", "label": "CI · main" } } ]
244
+ > </mac_actions>
245
+ > </mac_push>
259
246
  > ```
260
- > *(human says "next" → reply 2 with `1 / 3` swapped for `2 / 3` and the next email's body)*
261
247
 
262
248
  ---
263
249
 
264
250
  ## What Not To Do
265
251
 
266
- - ❌ **No long monologues.** If you can't say it in two sentences, you're either over-explaining or you should make the card carry it.
267
- - ❌ **No reading the card aloud.** The card and the speech complement each other; don't make them redundant.
268
- - **No external assets.** `<img src="https://…">`, `<link href="…">`, Google Fonts, none of it loads.
269
- - ❌ **No interactive elements.** Buttons render but do nothing they read as broken UI. Drop them.
270
- - ❌ **No light backgrounds.** The pill is black. White text on a white card looks like a missing texture.
271
- - ❌ **No emoji as primary content** unless it's the answer. They render small at 12px and lose meaning.
272
- - ❌ **Don't send a card "just because"** if the answer is a bare fact. The card should add something the voice can't carry — structure, list, comparison, status.
252
+ - ❌ **No long monologues.** Two sentences. If you can't, let the card carry it.
253
+ - ❌ **No reading the card aloud.** Voice + card complement, never duplicate.
254
+ - ⚠️ **Proactive `point`/`spotlight` is mapped against the current screen you can't see** — only use it when you truly know the location, else send a card.
255
+ - ❌ **No external assets** in custom HTMLno network in the notch view.
256
+ - ❌ **No interactive elements** in cards buttons render but do nothing.
257
+ - ❌ **No light backgrounds** the pill is black.
258
+ - ❌ **Don't send a visual "just because"** a bare fact needs no card.
259
+ - ❌ **Don't invent action `type`s** — only `card`, `point`, `spotlight` exist today.
273
260
 
274
261
  ---
275
262
 
276
263
  ## Reply Checklist
277
264
 
278
- Before you send:
279
-
280
- 1. **Did the tag `[Mac]` actually start the user message?** If not, don't use this skill.
281
- 2. **Is the spoken text 2 sentences, no markdown, no enumerations?**
282
- 3. **🚫 Does my spoken text recite items that are already in my card?** If yes, **rewrite the speech as a lead-in only** ("Here are the top five, Bruno."). Speaking the card aloud is the #1 failure mode of this skill. Re-read the spoken text and the card together — if you remove the card, would the voice still make sense as the standalone answer? If yes, you're double-answering. Trim the voice.
283
- 4. **If I'm sending a card, does it add structure the voice can't carry?** If a sentence covers it, drop the card.
284
- 5. **Does my voice acknowledge the card if I sent one?** ("Here it is.", "Pinned it up top.", etc.)
285
- 6. **Did I check for a PRESET first** ([`presets/PRESETS.md`](presets/PRESETS.md))? Only hand-write `<notch_html>` if no preset fits. (For custom, did I check `frequentSnippets/` for one I already made?)
286
- 7. **If it's a preset:** is the body **valid JSON**, and is `type` one of the real preset names (lowercase)?
287
- 8. **If it's custom:** is the card ≤ 383×147pt, transparent-on-black, white text, no external assets?
288
- 9. **Is the tag spelled exactly `<notch_card type="…">…</notch_card>` or `<notch_html>…</notch_html>` (lowercase, underscore)?**
289
- 10. **If I'm offering to save a custom card for next time, did I say so plainly?**
265
+ 1. Did the message actually start with `[Mac]`? If not, don't use this skill.
266
+ 2. Spoken text ≤ 2 sentences, no markdown, no enumerations?
267
+ 3. 🚫 Does my speech recite what's already in my card? Rewrite it as a lead-in only.
268
+ 4. If acting on screen, did I read the coordinates off **this turn's screenshot**, and set `screen` if multi-display?
269
+ 5. Is my `<mac_actions>` value **valid JSON** (an array of objects, each with a `type`)?
270
+ 6. For a `card`: did I check **PRESETS.md** first, and is `preset` a real lowercase name with valid `data`?
271
+ 7. For a custom card: raw `<notch_html>`, 383×147, transparent-on-black, white text, no external assets?
272
+ 8. Proactive? Wrapped in `<mac_push>`, no `point`/`spotlight`, and brief?
273
+ 9. Does my voice acknowledge the visual if I sent one?
290
274
 
291
275
  ---
292
276
 
@@ -294,14 +278,16 @@ Before you send:
294
278
 
295
279
  | Thing | Where / how |
296
280
  |---|---|
297
- | Tag that activates this skill | `[Mac]` at the start of the user message |
298
- | **Preset card tag (preferred)** | `<notch_card type="…">{json}</notch_card>` |
299
- | Preset catalog + schemas | [`presets/PRESETS.md`](presets/PRESETS.md) — email, list, calendar, weather, ticker, stat, info, text, comparison |
300
- | Custom card tag (escape hatch) | `<notch_html>…</notch_html>` (singular, anywhere in your reply) |
301
- | Canvas size | **383 × 147 pt**, transparent over **black** |
302
- | Custom snippet library | `workspace/skills/mac/frequentSnippets/*.html` |
303
- | TTS engine | ElevenLabs (Morphy handles it; you just write the words) |
304
- | Stripped from speech | Anything inside `<notch_card …>…` or `<notch_html>…` (case-insensitive, multi-line) |
305
- | Long text | **Scrollable** the user scrolls long cards (email/list/calendar/text) with the trackpad |
306
- | Auto-opens notch? | Yes sending a card notch slides down automatically as audio starts |
307
- | Auto-clears? | When the human triggers the next push-to-talk, or after the safety timer |
281
+ | Activates this skill | `[Mac]` at the start of the user message |
282
+ | **Action registry** | `<mac_actions>[ { "type": "…", }, ]</mac_actions>` — one block, JSON array, runs in order |
283
+ | Action types | `card` (preset), `point`, `spotlight` |
284
+ | `card` | `{ "type":"card", "preset":"…", "data":{…} }` catalog: [`presets/PRESETS.md`](presets/PRESETS.md) |
285
+ | `point` | `{ "type":"point", "x", "y", "label"?, "screen"? }` — best on a reply; proactive maps to the current screen |
286
+ | `spotlight` | `{ "type":"spotlight", "x","y", "r"?, "label"?, "screen"? }` — best on a reply; proactive maps to the current screen |
287
+ | Custom card (raw) | `<notch_html>…</notch_html>` raw markup, no escaping |
288
+ | Custom snippet library | [`frequentSnippets/`](frequentSnippets/)`*.html` |
289
+ | Proactive push | wrap payload in `<mac_push>…</mac_push>` (cards only, no point/spotlight) |
290
+ | Canvas | **383 × 147 pt**, transparent over **black** |
291
+ | Stripped from speech | Anything inside `<mac_actions>`, `<notch_html>` (and legacy `<notch_card>` / `<morphy_action>`) |
292
+ | Coordinates | screenshot pixels (top-left origin); `screen` is 1-based |
293
+ | Auto-clears | next push-to-talk, or a short safety timer |