Below is the full skill, rendered for reading. Embedded widget markup is shown as source — it is an instruction to the agent, not something this page runs.
xTiles Evening Reflection — Setup & Daily Wrap-Up
The evening bookend to the morning Daily Brief. Where the morning brief points forward at signals to act on, the evening reflection looks back: it synthesizes what actually happened today, optionally logs it as completed tasks, and seeds tomorrow.
Three principles
- Survey first, write to xTiles last. On setup and on the first manual run, nothing is created until the user has seen a preview and approved it. Only scheduled runs (with an approved config) act autonomously.
- Real data, not placeholders. Always pull from the user's own past Claude
chats via
recent_chats(no connector needed) and from any connected tools before preview so the user sees live content. Never invent names, meetings, or messages — and never reconstruct the day from this session's context instead of reading it. - Match the user's language throughout the entire flow — match the language of the user's first message and adapt if they switch. On a scheduled run there is no user message: use the language of the scheduled-task config prompt, and if that is ambiguous, the language of the fetched content. Default to English when still unclear. Every template, label, and example in this file is written in English as a placeholder — translate them into the detected language, and never emit a label in a language the user has not used.
- Every write to the planner is immediately followed by a layout pass — automatically, no exceptions. The instant the reflection tile is added in step 7, re-lay-out only that new tile into a justified grid (step 7's layout pass, via the shared
tile-layoutworkflow) before anything else — before the CTA button, before the schedule widget, before any message to the user. This never waits for the user to ask, is never skipped as "not needed this time," and is never left for a later run.
Algorithm
Period is always Daily. At the start of setup, tell the user: "I'll set up your Evening Reflection — a short end-of-day synthesis written to your Daily planner page." Never ask which period to set up. If the user asks for Weekly or Monthly, say only the Daily reflection is currently supported.
Run mode — detect before step 1:
- Scheduled run: the incoming message contains
role:,tools:,evening_content:,tone:, andautolog:(config injected by thescheduleskill). Do not show the survey. Extract the config from the message. If a connector from the config is not detected — offer to walk the user through connecting it before continuing. Then jump to step 4 (Silent data fetch). A scheduled run executes autonomously through to the written tile — but it still respects theautologflag (only auto-creates tasks if it was approved at setup). - Fast-track or fresh manual run: proceed to step 1.
1. Fast-track
If the user is specific ("reflect on my day using Slack and calendar") — skip the full survey. Minimum needed: which connectors to pull from — infer from the message, then check the detection table (step 2) to confirm availability. If a required connector is not detected — offer to walk the user through connecting it (see How to connect connectors); wait for confirmation. Pull only from connectors that are both mentioned and confirmed available. Jump to step 4.
If the request is general — run the full flow.
2. Detect what's connected — silently, don't ask
Never ask the user what they have connected. Detect it yourself by checking which MCP tools are present in this session, and treat that as the source of truth. The survey (step 3) is only about preferences, never about connection status.
| Connector | Identifying MCP tools |
|---|---|
| Claude (past chats) | recent_chats, conversation_search — not a connector: present by default, nothing to connect, and never offered in a connect flow |
| xTiles | mcp__xtiles__xtiles_create_tiles_from_markdown_in_my_planner, mcp__xtiles__xtiles_list_tasks |
| Slack | mcp__claude_ai_Slack__slack_search_channels, mcp__claude_ai_Slack__slack_read_channel |
| Gmail | mcp__claude_ai_Gmail__search_threads, mcp__claude_ai_Gmail__get_thread |
| Calendar | the available calendar/events MCP tool, if any |
| Linear | mcp__claude_ai_Linear__list_issues |
Build the detected set from this. Connecting is only ever raised in two cases:
- xTiles is the only hard requirement. If xTiles is not detected — stop and walk the user through connecting it (see How to connect connectors). Wait for confirmation before continuing.
- The user explicitly wants a source that isn't detected (e.g. picks "add
another tool" in the survey, or names one). Then offer to connect it via
mcp__mcp-registry__suggest_connectors. If they decline — just skip that source and continue. Never block the flow on an optional connector, and never prompt to connect something that is already detected.
These connectors are external and optional — they are not shipped with this plugin.
3. Reflection preferences
Reconcile the survey's source picks against the detected set from step 2: pre-check the tools that are already connected, pull only from detected sources, and treat an "Other…" / not-detected pick as the only trigger to offer connecting. Never re-prompt to connect something already detected.
Ask three things (folded into the survey widget; inline in Claude Code):
3.1 What to reflect on each evening. Options — include only those relevant to connected tools:
- Slack threads you were active in (only if Slack connected)
- Emails you sent / that needed action (only if Gmail connected)
- Meetings & calls (from calendar/notes) (if calendar/Granola connected)
- Tasks you completed today (xTiles — on by default)
- Other (describe in next message)
3.2 Tone. Single select:
- Honest coach — direct, names weak days plainly, anti-fluff (default)
- Gentle — supportive and encouraging
- Neutral — plain factual summary, no editorializing
3.3 Auto-log completed tasks. Single select:
- Yes, with a preview first — show me the tasks before creating them, then do it automatically on scheduled runs (recommended default)
- Yes, automatically — just create and complete them, no preview
- No — don't auto-create tasks, only write the reflection tile
If Slack is selected and the user has not named channels: call
mcp__claude_ai_Slack__slack_search_channels with query general, show up to 6 channel names. Ask via
AskUserQuestion (multi allowed): "Which channels reflect your real work? Pick
all that matter." Include found channels plus a fixed "Other — I'll type the
names" option. Add typed names as-is.
Ignored Slack noise (configurable). By default, ignore automated/bot channels and alert streams (Sentry/error bots, build/deploy notifications, health/status channels). Do not hardcode specific company channel names — derive the filter from channel metadata (bot-posted, app-integration) and let the user add or remove channels. If the user names channels to always ignore, store them in the config.
General rule: if the user writes something custom — add it as-is. Don't reshape it into a predefined option.
4. Silent data fetch
Silently, without messaging the user, pull today's data. First resolve context:
mcp__xtiles__xtiles_get_user_timezone— the user's IANA timezone and current local datetime. Use it to define "today" (00:00–23:59 local) and to resolve dates.mcp__xtiles__xtiles_get_current_user— the user's name, email, and xTiles user id. Do not rely on injected template variables for identity.
Then pull from selected connectors:
- xTiles tasks (PRIMARY SOURCE):
mcp__xtiles__xtiles_list_taskswithcompleted: "true",due_date_after: today,due_date_before: tomorrow,per_page: 50. Repeat withcompleted: "false"for open tasks due today. Alsomcp__xtiles__xtiles_get_planner_contentwithperiod: "day"and today's date for full day context. - Slack:
slack_search_public_and_privatewithon:[today] from:[user]to find where the user was active, thenslack_read_threadon the important threads. Apply the ignore filter from step 3. - Gmail:
mcp__claude_ai_Gmail__search_threadsfor mail sent today and important received mail that needed action (newer_than:1d), thenget_threadfor sender/subject/threadId. - Calendar / meeting notes (if connected): today's events; separate meetings-with-others (attendees > 1) from solo work blocks.
- Claude chat history (today) — always run, no connector needed: call
recent_chatswithafter= today 00:00 andbefore= now, both ISO-8601 in the user's timezone fromxtiles_get_user_timezone(never UTC — an evening run in a +2 zone would otherwise pull the wrong day),sort_order: "desc", ~10 chats. Page back withbeforeset to the oldest chat you got while the results still fall inside today; stop at the first one that doesn't. Extract concrete outcomes — what was actually built, solved, decided, or shipped (e.g. "wrote the launch email", "fixed the auth bug", "researched competitors"). Ignore abandoned or purely exploratory threads. These outcomes feed both the reflection and the auto-log.- Use
conversation_searchonly to close a specific gap — a thread that clearly continues earlier work, or a task from the xTiles list you suspect was finished in a chat and want to confirm before auto-logging it. One query per gap,max_results: 5, and keep only hits from today. Never sweep the archive. - Exclude this workflow's own chats — the reflection run itself, the
morning
daily-briefrun, and any setup/survey conversation are machinery, not outcomes. "Ran my evening reflection" is never an achievement. - Keep each outcome's conversation URL as returned by the tool — it is what lets the reflection link back to where the work happened. Never build a chat URL by hand.
- If
recent_chatsis unavailable or errors — treat it exactly like a failed connector below: drop the source, say so explicitly, and build the reflection from xTiles tasks and the remaining connectors. Never fall back to this session's own context, and never invent a day.
- Use
Use only real data from connectors. If a connector call fails (error, timeout, 401) — record the failure and surface it explicitly later as "Could not fetch [connector] — connector error" (never silently write "No data").
5. Auto-log preview & write (respect the autolog setting)
Compare today's real activity — including outcomes pulled from Claude chat history — against the existing xTiles task list, and decide per activity:
- Close existing — if the activity matches an open task due today (same
work, even if worded differently), just mark that task complete with
mcp__xtiles__xtiles_update_task(completed: true). Do not create a duplicate. - Create + close — if the activity has no matching task, create it with
mcp__xtiles__xtiles_create_tasksand immediately mark it complete. - Skip — if a completed task for it already exists.
Match generously on meaning, not exact wording (e.g. a Claude chat "wrote the launch email" closes an open task "Draft launch email").
What counts as an activity (derive categories from the data and the user's role — do not force a fixed founder/PM template):
- 📞 Meetings & calls
- 💬 Interviews / CustDev / user or partner conversations
- 📝 Content created (posts, emails, docs, significant Slack messages)
- 🤝 Partnership or relationship moves — new contacts, agreements, follow-ups
- 🔧 Support / access granted
- 🔬 Research, analysis, deep dives
- 🛠 Materials prepared (decks, webinars)
- 🗺 Strategic decisions or priority shifts
Behavior by autolog setting:
- Yes, with a preview first (and on the first manual run regardless): show the
proposed list in chat, marking each as new or closing an existing task —
✅ [emoji] short specific titlefor new,☑️ closes: "[existing task]"for matches — and ask viaAskUserQuestion: "Log these for today?" → Apply all / Edit the list / Skip. Only after approval, apply them. - Yes, automatically: create without preview.
- No: skip task creation entirely; go straight to the reflection tile.
To create: mcp__xtiles__xtiles_create_tasks with assignee_email (from
get_current_user), due_date: today (yyyy-MM-dd), title: short specific name
with an emoji category prefix. Then mark each completed:
mcp__xtiles__xtiles_update_task with completed: true. Avoid duplicates — never
recreate a task that already exists for today.
6. Compose the reflection & preview in chat
Derive themes dynamically from ALL collected data — never from a template. Determine: the main themes of the day; what actually moved something forward vs pure operations; opportunities (new contacts, ideas, competitive intel, insights); promises & follow-ups (what was promised, who needs a message).
Apply the chosen tone. If the day was quiet, say so honestly — don't stretch it. Optional sections appear only if there is something genuinely valuable.
Show the preview in chat with real content (not headings with "TBD"):
Here's your reflection for [actual date]:
---
✨ DAY CHARACTERISTIC — DD.MM.YYYY
[1–2 sharp sentences — the tone and essence of the day, not a task list]
🎯 RESULTS
- [What was done]
- ...
[If no strategic movement: "Operational day — little strategic progress"]
🌟 OPPORTUNITIES (only if non-trivial)
- [Specific finds: partnerships, leads, competitor intel, ideas]
→ TOMORROW
- [ ] Specific action with names — "Message X about Y", not "continue X"
- [ ] max 3 items
---
After the preview, ask via AskUserQuestion: Looks good — write it /
Change something / Cancel. On scheduled runs, skip approval and write
directly.
7. Write to xTiles
Only after approval (or on a scheduled run).
Tool: mcp__xtiles__xtiles_create_tiles_from_markdown_in_my_planner
period: "day"date: today in ISO 8601markdown: all sections in a single call — never split per section.
Append, don't clobber. The evening reflection writes to the same Daily page
the morning brief uses. First call mcp__xtiles__xtiles_get_planner_content for
today; compare existing ### headers; append only sections whose headers don't
exist yet. If everything already exists, ask: replace, append anyway, or cancel.
One single tile. The whole reflection is one ### tile titled
✨ Day Characteristic — DD.MM.YYYY — not separate tiles per section. The color
annotations sit on the two lines directly below the title (no blank line
between the title and the annotations):
### ✨ Day Characteristic — DD.MM.YYYY
@colorSize: LIGHTER
@color: SAIL
**[1–2 sharp sentences — the tone and essence of the day]**
---
**🎯 Results**
- [What was done]
---
**🌟 Opportunities**
- [Specific finds]
---
**→ Tomorrow**
- [ ] [Specific action with names — "Message X about Y", not "continue X"]
- [ ] [max 3 items total]
⚠️ [unavailable connectors, only if some failed]
@colorSizeis alwaysLIGHTER;@coloris alwaysSAILfor this tile. (Do not use plain names like "purple" — they will not render.)- Sections inside the tile are bold subheaders (
**🎯 Results**), separated by---dividers — never separate###tiles. - Drop any optional section (Opportunities) entirely if there's nothing genuinely valuable — don't leave an empty header.
Content formatting inside the tile:
- Separate each item with a blank line — never a continuous block.
- Slack/email entries that have a URL are Markdown hyperlinks with the priority
emoji BEFORE the
[, never inside the brackets. An outcome that came from a chat follows the same rule, linked to the conversation URLrecent_chatsreturned — the chat title is the link text. If the tool returned no URL, write the title as plain text; never fabricate aclaude.ailink. - Tomorrow's actions as task blocks (
- [ ] Task name), one empty line between each — never a numbered list. - Append the final
⚠️ [unavailable connectors]line only if a connector failed.
After a successful write — run these steps in order, no exceptions. Step 2 (the layout pass) is not optional and is never deferred, asked about, or judgment-called away — it runs automatically, immediately after every single write, before step 3's CTA button is even composed:
- Write
✅ Evening reflection saved. - Layout pass — mandatory, silent, automatic, every single run (scheduled runs included, fast-track included, any tile count included). Using the
view_idandtile_idsreturned by the write call above (tile_idsis ordered to match the###sections you just wrote — here a single reflection tile), apply the shared justified-grid layout rules: callmcp__xtiles__xtiles_get_workflowwith idtile-layoutand follow it exactly — treat the tiles intile_idsas its "added tiles" and the markdown you just composed as their content. Layout hints for this workflow: always exactly 1 tile (the reflection) · give it a generous width — max_width, or the largest free band next to existing tiles. Do not message the user about this pass, do not ask for confirmation, and never skip it — not even for a single tile or a scheduled run. (You may fetchtile-layoutonce per session and reuse it on later runs.) - Call
mcp__xtiles__xtiles_get_planner_contentfor the same date/period, extractview_id. Callshow_widgetwith the CTA widget HTML (see below), replacing{VIEW_URL}withhttps://xtiles.app/{view_id}. Translate the button label into the user's language. Never output a markdown link instead of the widget — the button must render every time. - Immediately continue to step 8 (Schedule) — do not skip, do not ask first.
On error, say briefly what went wrong and offer to retry.
8. Schedule (optional)
After every successful manual write — show the schedule widget (see below), regardless of survey answers. In Claude Code, ask inline: "Want me to run this every evening automatically? What time? (default: 9:00 PM)".
- If the user schedules it — invoke
anthropic-skills:schedule, thenmcp__scheduled-tasks__create-scheduled-tasks. Pass to both:prompt: full config assembled from setup —
Replace all placeholders with real values.Run evening reflection — role: {role} · tools: {tools} · evening_content: {content} · tone: {tone} · autolog: {on/preview/off} · schedule: daily-9pmschedule: cron derived from the widget. The widget sendscron: HH:MM days:1-5(weekdays) orcron: HH:MM days:*(every day) — parse both values and build:M H * * 1-5for weekdays,M H * * *for every day. Default0 21 * * 1-5(9:00 PM on weekdays) if not found.timezone: frommcp__xtiles__xtiles_get_user_timezone. This prompt fires each evening and triggersevening-reflectionin scheduled-run mode — the full config must be embedded so the survey is skipped. Confirm: "Done — your reflection will write to xTiles every [weekday evening / evening] at [time]." (say "weekday evening" ifdays:1-5, "every evening" ifdays:*)
- If the user declines — acknowledge briefly.
Either way, continue to step 9 (Related workflows) — do not stop here.
9. Related workflows
After every manual run, once step 8 is resolved (scheduled or declined) — offer related workflows. Skip this on scheduled runs, which end silently after step 7.
Ask via AskUserQuestion (single select): "Want to set up anything else on
xTiles?"
- 🌅 Daily Brief — a live morning brief from your connected tools
- 📰 Today News — a daily news digest on topics you care about
- 📊 Weekly Review — a weekly summary of what moved forward this week
- Nothing else, thanks
Never list these as plain text requiring the user to retype a choice — always use the interactive question.
On selection, send the exact matching phrase to hand off to that skill (do not attempt to run it yourself):
- Daily Brief →
Set workflow of Daily Brief (daily-brief) on xTiles MCP - Today News →
Set workflow of Today News (today-news) on xTiles MCP - Weekly Review →
Set workflow of Weekly Review (weekly-review) on xTiles MCP - "Nothing else" — acknowledge briefly and stop.
How to connect connectors
Do not send the user to settings manually and do not give a URL to follow.
Call mcp__mcp-registry__suggest_connectors — it renders interactive connect
buttons directly in the Cowork UI.
Flow:
- Call
mcp__mcp-registry__suggest_connectorswith the names of missing connectors. - Show the Done widget (below) directly under the connector form.
- The user clicks the connect buttons; auth runs natively. When finished, they click "Done".
- Confirm: "Connected. Continuing…" and resume from where the flow paused.
Done widget HTML
Show via show_widget immediately after calling
mcp__mcp-registry__suggest_connectors.
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;padding:16px;background:transparent}
.btn{width:100%;padding:11px 20px;border-radius:10px;border:none;font-size:14px;font-weight:600;cursor:pointer;background:#1a1a1a;color:#fff;transition:background .15s}
.btn:hover{background:#333}
</style>
<button class="btn" id="btn-done" onclick="doneIt()">✓ Done</button>
<script>
function doneIt(){var b=document.getElementById('btn-done');b.disabled=true;b.style.opacity='0.5';b.style.cursor='default';b.textContent='⏳…';sendPrompt('Done — connectors connected, continue the flow');}
</script>
Survey widget HTML
Show via show_widget at the start of setup in Cowork. After Submit, the user
sends a string of answers to chat — process it and continue.
<style>
:root{--color-background-primary:#fff;--color-background-secondary:#f5f5f5;--color-background-tertiary:#f8f8f8;--color-text-primary:#1a1a1a;--color-text-secondary:#888;--color-border-secondary:#aaa;--color-border-tertiary:#e0e0e0}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;padding:20px;background:var(--color-background-tertiary);color:var(--color-text-primary)}
.wrap{max-width:560px;margin:0 auto;background:var(--color-background-primary);border-radius:16px;padding:28px;box-shadow:0 2px 12px rgba(0,0,0,.08)}
h2{font-size:18px;font-weight:700;margin-bottom:4px}
.step-label{font-size:12px;color:var(--color-text-secondary);margin-bottom:20px}
.sec{margin-bottom:22px}
.sec-title{font-size:13px;font-weight:600;margin-bottom:8px}
.hint{font-size:12px;color:var(--color-text-secondary);margin-bottom:8px}
.pills{display:flex;flex-wrap:wrap;gap:7px}
.pill{padding:6px 14px;border-radius:20px;border:1.5px solid var(--color-border-tertiary);font-size:13px;cursor:pointer;background:var(--color-background-primary);user-select:none;transition:all .15s}
.pill:hover{border-color:var(--color-border-secondary)}
.pill.sel{background:var(--color-text-primary);color:var(--color-background-primary);border-color:var(--color-text-primary)}
.cards{display:flex;flex-wrap:wrap;gap:8px}
.card{display:flex;align-items:center;gap:7px;padding:8px 13px;border-radius:10px;border:1.5px solid var(--color-border-tertiary);font-size:13px;cursor:pointer;background:var(--color-background-primary);user-select:none;transition:all .15s}
.card:hover{border-color:var(--color-border-secondary)}
.card.sel{background:var(--color-text-primary);color:var(--color-background-primary);border-color:var(--color-text-primary)}
.chk{width:15px;height:15px;border-radius:4px;border:1.5px solid var(--color-border-secondary);display:flex;align-items:center;justify-content:center;font-size:9px;flex-shrink:0}
.card.sel .chk{background:var(--color-background-primary);border-color:var(--color-background-primary);color:var(--color-text-primary)}
.custom-in{margin-top:9px}
.custom-in input{width:100%;padding:7px 11px;border:1.5px solid var(--color-border-tertiary);border-radius:8px;font-size:13px;outline:none}
.checks{display:flex;flex-direction:column;gap:5px;margin-top:6px}
.ci{display:flex;align-items:center;gap:9px;padding:7px 11px;border-radius:8px;border:1.5px solid var(--color-border-tertiary);font-size:13px;cursor:pointer;user-select:none;transition:all .15s}
.ci:hover{border-color:var(--color-border-secondary)}
.ci.sel{border-color:var(--color-text-primary);background:var(--color-background-secondary)}
.ci.sel .chk{background:var(--color-text-primary);border-color:var(--color-text-primary);color:var(--color-background-primary)}
.btn-row{display:flex;gap:10px;margin-top:22px}
.btn{padding:9px 18px;border-radius:10px;border:none;font-size:14px;font-weight:600;cursor:pointer;transition:all .15s}
.btn-p{background:var(--color-text-primary);color:var(--color-background-primary);flex:1}
.btn-p:hover:not(:disabled){opacity:.9}
.btn-p:disabled{opacity:.5;cursor:not-allowed}
.btn-s{background:var(--color-background-secondary)}
</style>
<div class="wrap" id="app">
<!-- STEP 1 -->
<div id="s1">
<div class="step-label">Step 1 of 2</div>
<h2>About you</h2>
<div class="sec" style="margin-top:18px">
<div class="sec-title">What's your role?</div>
<div class="pills" id="role-pills">
<div class="pill" onclick="pickRole(this,'Product Manager')">Product Manager</div>
<div class="pill" onclick="pickRole(this,'Designer')">Designer</div>
<div class="pill" onclick="pickRole(this,'Engineer')">Engineer</div>
<div class="pill" onclick="pickRole(this,'Growth & Marketing')">Growth & Marketing</div>
<div class="pill" onclick="pickRole(this,'Founder / CEO')">Founder / CEO</div>
<div class="pill" onclick="pickRole(this,'Support & Success')">Support & Success</div>
<div class="pill" onclick="pickRole(this,'__other__')">Other role…</div>
</div>
<div class="custom-in" id="role-other-wrap" style="display:none">
<input id="role-other-in" type="text" placeholder="Your role…" oninput="chkNext()">
</div>
</div>
<div class="sec">
<div class="sec-title">Which sources should feed your reflection?</div>
<div class="hint">Pre-checked = already connected. Pick "Other…" only to add a source you haven't connected yet.</div>
<div class="cards" id="tool-cards">
<div class="card" onclick="togTool(this,'Slack')"><div class="chk">✓</div>Slack</div>
<div class="card" onclick="togTool(this,'Gmail')"><div class="chk">✓</div>Gmail</div>
<div class="card" onclick="togTool(this,'Calendar')"><div class="chk">✓</div>Calendar</div>
<div class="card" onclick="togTool(this,'Granola')"><div class="chk">✓</div>Granola</div>
<div class="card" onclick="togTool(this,'Linear')"><div class="chk">✓</div>Linear</div>
<div class="card" onclick="togTool(this,'__other__')"><div class="chk">✓</div>Other…</div>
</div>
<div class="custom-in" id="tool-other-wrap" style="display:none">
<input id="tool-other-in" type="text" placeholder="Other tools (comma-separated)…">
</div>
</div>
<div class="btn-row">
<button class="btn btn-p" id="next-btn" onclick="go2()" disabled>Next →</button>
</div>
</div>
<!-- STEP 2 -->
<div id="s2" style="display:none">
<div class="step-label">Step 2 of 2</div>
<h2>Your evening reflection</h2>
<div class="sec" style="margin-top:18px">
<div class="sec-title">What should the reflection cover?</div>
<div class="checks" id="evening-content"></div>
</div>
<div class="sec">
<div class="sec-title">Tone</div>
<div class="pills" id="tone-pills">
<div class="pill sel" onclick="pickTone(this,'Honest coach')">Honest coach</div>
<div class="pill" onclick="pickTone(this,'Gentle')">Gentle</div>
<div class="pill" onclick="pickTone(this,'Neutral')">Neutral</div>
</div>
</div>
<div class="sec">
<div class="sec-title">Auto-log today's activities as completed tasks?</div>
<div class="pills" id="autolog-pills">
<div class="pill sel" onclick="pickLog(this,'preview')">Yes — preview first</div>
<div class="pill" onclick="pickLog(this,'auto')">Yes — automatically</div>
<div class="pill" onclick="pickLog(this,'off')">No</div>
</div>
</div>
<div class="btn-row">
<button class="btn btn-s" onclick="go1()">← Back</button>
<button class="btn btn-p" onclick="submit()">Set up reflection</button>
</div>
</div>
</div>
<script>
var role=null, tools=new Set(), content=new Set(), tone='Honest coach', autolog='preview';
var TM={
'Slack': ['Slack threads I was active in'],
'Gmail': ['Emails I sent / that needed action'],
'Calendar':['Meetings & calls'],
'Granola': ['Meeting notes & summaries'],
'Linear': ['Linear issues I moved']
};
var ROLE_DEFAULTS={
'Product Manager': ['Meetings & calls','Slack threads I was active in','Tasks I completed today'],
'Designer': ['Slack threads I was active in','Tasks I completed today'],
'Engineer': ['Linear issues I moved','Tasks I completed today','Slack threads I was active in'],
'Growth & Marketing':['Emails I sent / that needed action','Tasks I completed today','Meetings & calls'],
'Founder / CEO': ['Meetings & calls','Slack threads I was active in','Emails I sent / that needed action','Tasks I completed today'],
'Support & Success': ['Emails I sent / that needed action','Slack threads I was active in','Tasks I completed today']
};
function pickRole(el,v){document.querySelectorAll('#role-pills .pill').forEach(function(p){p.classList.remove('sel')});el.classList.add('sel');role=v;document.getElementById('role-other-wrap').style.display=v==='__other__'?'block':'none';chkNext();}
function togTool(el,v){el.classList.toggle('sel');if(v==='__other__'){document.getElementById('tool-other-wrap').style.display=el.classList.contains('sel')?'block':'none';}else{el.classList.contains('sel')?tools.add(v):tools.delete(v);}chkNext();}
function pickTone(el,v){document.querySelectorAll('#tone-pills .pill').forEach(function(p){p.classList.remove('sel')});el.classList.add('sel');tone=v;}
function pickLog(el,v){document.querySelectorAll('#autolog-pills .pill').forEach(function(p){p.classList.remove('sel')});el.classList.add('sel');autolog=v;}
function chkNext(){var ok=role&&(role!=='__other__'||document.getElementById('role-other-in').value.trim());document.getElementById('next-btn').disabled=!ok;}
function go2(){if(!content.size){var r=role==='__other__'?null:role;(ROLE_DEFAULTS[r]||['Tasks I completed today']).forEach(function(v){content.add(v);});}renderContent();document.getElementById('s1').style.display='none';document.getElementById('s2').style.display='block';}
function go1(){document.getElementById('s2').style.display='none';document.getElementById('s1').style.display='block';}
function renderContent(){
var items=['Tasks I completed today'];
tools.forEach(function(t){if(TM[t])TM[t].forEach(function(i){if(items.indexOf(i)<0)items.push(i)})});
var html='';
items.forEach(function(o){var s=content.has(o)?' sel':'';html+='<div class="ci'+s+'" onclick="togCI(this,\''+o.replace(/'/g,"\\'")+'\')"><div class="chk">✓</div>'+o+'</div>';});
html+='<div class="ci" onclick="togOther(this)"><div class="chk">+</div>Something else…</div>';
html+='<div class="custom-in" id="co-ev" style="display:none"><input type="text" placeholder="What else…"></div>';
document.getElementById('evening-content').innerHTML=html;
}
function togCI(el,v){el.classList.toggle('sel');el.classList.contains('sel')?content.add(v):content.delete(v);}
function togOther(el){el.classList.toggle('sel');var w=document.getElementById('co-ev');if(w)w.style.display=el.classList.contains('sel')?'block':'none';}
function submit(){
document.querySelectorAll('.btn').forEach(function(b){b.disabled=true;b.style.opacity='0.5';b.style.cursor='default';});
var r=role==='__other__'?document.getElementById('role-other-in').value.trim():role;
var tArr=Array.from(tools);var tOther=document.getElementById('tool-other-in').value.trim();if(tOther)tArr.push(tOther);
var items=Array.from(content);var inp=document.getElementById('co-ev');if(inp){var v=inp.querySelector('input');if(v&&v.value.trim())items.push(v.value.trim());}
sendPrompt('Evening reflection setup — role: '+r+' · tools: '+(tArr.join(', ')||'none')+' · evening_content: '+(items.join(', ')||'none')+' · tone: '+tone+' · autolog: '+autolog);
}
</script>
Schedule widget HTML
Show via show_widget after a successful write in Cowork. Default time is evening.
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;padding:20px;background:#f8f8f8;color:#1a1a1a}
.wrap{max-width:480px;margin:0 auto;background:#fff;border-radius:16px;padding:28px;box-shadow:0 2px 12px rgba(0,0,0,.08);text-align:center}
.icon{font-size:36px;margin-bottom:12px}
h2{font-size:17px;font-weight:700;margin-bottom:6px}
.sub{font-size:13px;color:#888;margin-bottom:20px;line-height:1.5}
.time-row{display:inline-flex;align-items:center;gap:8px;background:#f3f3f3;border-radius:10px;padding:8px 16px;font-size:13px;font-weight:600;color:#444;margin-bottom:24px}
.time-row select,.time-row input[type=time]{border:none;background:transparent;font-size:15px;font-weight:700;color:#1a1a1a;outline:none;cursor:pointer}
.btns{display:flex;flex-direction:column;gap:10px}
.btn{padding:11px 20px;border-radius:10px;border:none;font-size:14px;font-weight:600;cursor:pointer;transition:all .15s}
.btn-yes{background:#1a1a1a;color:#fff}
.btn-yes:hover{background:#333}
.btn-no{background:#f0f0f0;color:#555}
.btn-no:hover{background:#e0e0e0}
</style>
<div class="wrap">
<div class="icon">🌙</div>
<h2>Reflect every evening?</h2>
<p class="sub">I'll synthesize your day and write it to xTiles automatically — no need to ask each time.</p>
<div class="time-row">
📅 Every
<select id="sched-days">
<option value="1-5" selected>Weekdays</option>
<option value="*">Day</option>
</select>
at <input type="time" id="sched-time" value="21:00">
</div>
<div class="btns">
<button class="btn btn-yes" id="btn-yes" onclick="scheduleIt()">Yes, schedule it</button>
<button class="btn btn-no" id="btn-no" onclick="noThanks()">No, thanks</button>
</div>
</div>
<script>
function collapse(msg){document.querySelector('.btns').innerHTML='<p style="font-size:13px;color:#aaa;text-align:center;padding:4px 0">'+msg+'</p>';}
function scheduleIt(){
var days=document.getElementById('sched-days').value;
var t=document.getElementById('sched-time').value||'21:00';
var parts=t.split(':'),h=parseInt(parts[0],10),m=parts[1];
var label=(h%12||12)+':'+m+' '+(h>=12?'PM':'AM');
var dLabel=days==='1-5'?'weekdays':'every day';
collapse('⏳ Scheduling…');
sendPrompt('Yes, schedule my evening reflection at '+label+' '+dLabel+' (cron: '+t+' days:'+days+')');
}
function noThanks(){collapse('✓ Got it');sendPrompt('No schedule needed');}
</script>
CTA widget HTML
Show immediately after a successful write and after scheduling confirmation. Replace {VIEW_URL} with the real xTiles page URL before calling show_widget.
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;padding:12px;background:transparent}
.btn{display:block;width:100%;padding:12px 20px;border-radius:10px;font-size:15px;font-weight:700;color:#fff;background:#1a1a1a;text-align:center;text-decoration:none;transition:background .15s}
.btn:hover{background:#333}
</style>
<a class="btn" href="{VIEW_URL}" target="_blank">Open in xTiles →</a>
How to behave
- Use the survey widget for setup; use
AskUserQuestionfor every follow-up (channels, auto-log approval, preview approval, change requests). In Claude Code, ask the same questions inline. - Never write the reflection as plain chat text and ask the user to copy it — always write to xTiles, or walk through connecting xTiles first.
- Don't ask what's connected — detect it. Only xTiles is mandatory to connect. For any other source the user explicitly wants but isn't connected, offer to connect; if they decline, skip it and continue. Never prompt to connect something already detected.
- Never create tasks or tiles without preview and approval on setup / first
manual run. Only an approved scheduled run acts autonomously, and it still
respects the
autologsetting. - Respect the tone setting. If the day was quiet, say so honestly — don't stretch it. Optional sections appear only when there's real value.
- Derive themes and activity categories from the data, never from a fixed template, and never hardcode company-specific channel names.
- Real data from connectors always beats placeholders — never invent names, meetings, or messages.
- Identity (name, email, user id) comes from
xtiles_get_current_user; dates fromxtiles_get_user_timezone. - Daily is the only period. If asked for Weekly/Monthly, offer the Daily reflection instead — never silently downscope.
- Match the user's language; adapt if they switch.
- Show widgets in Cowork only — in Claude Code, ask the same questions inline.
- The CTA button (step 7) is not optional. Always call
show_widgetwith the CTA widget after a successful write — never end the write step with just the confirmation text. - Never end the flow with a plain-text list of next steps. After
scheduling is resolved (step 8), always offer related workflows through the
AskUserQuestionin step 9 — the user picks, they never retype a choice.