@masslessai/push-todo 3.10.3 → 3.10.5

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.
package/SKILL.md CHANGED
@@ -54,7 +54,12 @@ When this command is invoked:
54
54
  - Follow the [Auto-Resume from Session Transcript](#auto-resume-from-session-transcript) procedure below
55
55
  - Only if the session transcript cannot be found should you begin working from scratch
56
56
 
57
- 9. If no resumable session exists, begin working on the task normally
57
+ 9. **Load task attachments** before starting work:
58
+ - If the task has **screenshot attachments**: Read each image from `~/Library/Mobile Documents/iCloud~ai~massless~push/Documents/Screenshots/<filename>` using the Read tool. These provide essential visual context.
59
+ - If the task has **link attachments**: Use WebFetch to read linked content when relevant to the task.
60
+ - See [Reading Task Attachments](#reading-task-attachments) for full details.
61
+
62
+ 10. If no resumable session exists, begin working on the task normally
58
63
 
59
64
  ## Review Mode
60
65
 
@@ -339,6 +344,57 @@ Do NOT offer to start working on the task — the daemon is already handling it.
339
344
  If the session file cannot be found (daemon just started, no output yet):
340
345
  - Tell the user: "The daemon just started working on this task. Run `/push-todo <number>` again in a minute for a progress update."
341
346
 
347
+ ## Reading Task Attachments
348
+
349
+ Tasks can have **screenshot images** and **reference links** attached. When working on a task, always check for and use these attachments — they provide critical visual and reference context.
350
+
351
+ ### Screenshot Attachments
352
+
353
+ Screenshots are images captured from the user's phone screen when creating the task. They're stored in **iCloud Documents** and synced to the Mac automatically.
354
+
355
+ **When the task output shows an Attachments > Screenshots section:**
356
+
357
+ 1. **Get the filename** from the task output (e.g., `ABC123.png`)
358
+ 2. **Read the image** directly from the iCloud folder:
359
+ ```
360
+ ~/Library/Mobile Documents/iCloud~ai~massless~push/Documents/Screenshots/<filename>
361
+ ```
362
+ 3. **Use the Read tool** to view the image — Claude Code is multimodal and can interpret screenshots
363
+
364
+ Example:
365
+ ```bash
366
+ # The task shows: "1. ABC123.png (1170x2532)"
367
+ # Read it directly:
368
+ ```
369
+ Then use the Read tool on:
370
+ `~/Library/Mobile Documents/iCloud~ai~massless~push/Documents/Screenshots/ABC123.png`
371
+
372
+ **Why this matters:** Screenshots often contain the actual UI, error message, design mockup, or reference material the user was looking at when they created the task. The voice transcript alone may say "fix this" — the screenshot shows WHAT to fix.
373
+
374
+ **If the file doesn't exist locally:** iCloud may not have synced it yet. Tell the user: "The screenshot hasn't synced from iCloud yet. Try opening Finder > iCloud Drive > Push > Screenshots to trigger the download."
375
+
376
+ ### Link Attachments
377
+
378
+ Links are reference URLs the user shared when creating the task (e.g., from Safari, WeChat, or other apps).
379
+
380
+ **When the task output shows an Attachments > Links section:**
381
+
382
+ 1. Links are displayed as clickable markdown: `🔗 [Title](URL)`
383
+ 2. **Use WebFetch** to read the linked content when relevant to the task
384
+ 3. The `contextApp` field shows which app the link came from (e.g., "Safari", "WeChat")
385
+
386
+ ### Programmatic Access (JSON mode)
387
+
388
+ For scripts or when you need raw attachment data:
389
+ ```bash
390
+ push-todo <number> --json
391
+ ```
392
+
393
+ Key JSON fields:
394
+ - `screenshotAttachmentsJson` — JSON string array of `{id, imageFilename, width, height, capturedAt, sourceApp}`
395
+ - `linkAttachmentsJson` — JSON string array of `{id, url, title, createdAt}`
396
+ - `contextApp` — App the user was in when creating the task
397
+
342
398
  ## CLI Reference
343
399
 
344
400
  The `push-todo` CLI supports these commands:
package/lib/cli.js CHANGED
@@ -393,7 +393,8 @@ export async function run(argv) {
393
393
  process.exit(1);
394
394
  }
395
395
 
396
- const screenshots = task.screenshot_attachments || task.screenshotAttachments || [];
396
+ const raw = task.screenshotAttachmentsJson || task.screenshotAttachments || task.screenshot_attachments;
397
+ const screenshots = !raw ? [] : Array.isArray(raw) ? raw : (() => { try { return JSON.parse(raw); } catch { return []; } })();
397
398
  if (screenshots.length === 0) {
398
399
  console.error(red(`Task #${displayNumber} has no screenshot attachments`));
399
400
  process.exit(1);
@@ -6,6 +6,18 @@
6
6
 
7
7
  import { bold, dim, green, yellow, red, cyan, muted, symbols } from './colors.js';
8
8
 
9
+ /**
10
+ * Parse a JSON string field into an array. Handles strings, arrays, null/undefined.
11
+ */
12
+ function parseJsonField(value) {
13
+ if (!value) return [];
14
+ if (Array.isArray(value)) return value;
15
+ if (typeof value === 'string') {
16
+ try { return JSON.parse(value); } catch { return []; }
17
+ }
18
+ return [];
19
+ }
20
+
9
21
  /**
10
22
  * Format a duration in seconds to human-readable string.
11
23
  *
@@ -85,9 +97,9 @@ export function formatTaskForDisplay(task) {
85
97
  lines.push(task.content || task.normalizedContent || 'No content');
86
98
  lines.push('');
87
99
 
88
- // Attachments
89
- const screenshots = task.screenshotAttachments || task.screenshot_attachments || [];
90
- const links = task.linkAttachments || task.link_attachments || [];
100
+ // Attachments — API returns JSON strings (screenshotAttachmentsJson, linkAttachmentsJson)
101
+ const screenshots = parseJsonField(task.screenshotAttachmentsJson || task.screenshotAttachments || task.screenshot_attachments);
102
+ const links = parseJsonField(task.linkAttachmentsJson || task.linkAttachments || task.link_attachments);
91
103
 
92
104
  if (screenshots.length > 0 || links.length > 0) {
93
105
  lines.push('### Attachments');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masslessai/push-todo",
3
- "version": "3.10.3",
3
+ "version": "3.10.5",
4
4
  "description": "Voice tasks from Push iOS app for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {