@masslessai/push-todo 3.6.4 → 3.6.6
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 +94 -29
- package/lib/daemon.js +4 -3
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -36,13 +36,23 @@ When this command is invoked:
|
|
|
36
36
|
|
|
37
37
|
5. Ask which task the user wants to work on
|
|
38
38
|
|
|
39
|
-
6. **Check
|
|
39
|
+
6. **Check if the daemon is currently working on this task:**
|
|
40
|
+
- If the task output shows `**Status:** 🔄 Running`:
|
|
41
|
+
- The daemon is actively working on this task RIGHT NOW
|
|
42
|
+
- Follow the [Live Session Status](#live-session-status) procedure to show progress
|
|
43
|
+
- Do NOT start working on this task — the daemon is already on it
|
|
44
|
+
- If the task output shows `**Status:** ⚡ Queued for Mac execution`:
|
|
45
|
+
- The task is queued and waiting for the daemon to pick it up
|
|
46
|
+
- Tell the user: "This task is queued and will be picked up by the daemon shortly."
|
|
47
|
+
- Do NOT start working on this task
|
|
48
|
+
|
|
49
|
+
7. **Check for resumable daemon sessions:**
|
|
40
50
|
- If the task output contains `**Session:** Resumable`, the daemon already ran Claude Code on this task
|
|
41
51
|
- Do NOT start working from scratch — automatically load the daemon's session context
|
|
42
52
|
- Follow the [Auto-Resume from Session Transcript](#auto-resume-from-session-transcript) procedure below
|
|
43
53
|
- Only if the session transcript cannot be found should you begin working from scratch
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
8. If no resumable session exists, begin working on the task normally
|
|
46
56
|
|
|
47
57
|
## Review Mode
|
|
48
58
|
|
|
@@ -203,13 +213,64 @@ If no CLAUDE.md or README.md exists, generate minimal keywords from:
|
|
|
203
213
|
- Git repo name
|
|
204
214
|
- Primary file extensions (`.swift` -> iOS, `.py` -> Python, `.rs` -> Rust)
|
|
205
215
|
|
|
206
|
-
## Auto-Resume from Session
|
|
216
|
+
## Auto-Resume from Daemon Session
|
|
207
217
|
|
|
208
|
-
When a task has a resumable daemon session,
|
|
218
|
+
When a task has a resumable daemon session, use the git worktree branch directly instead of starting from scratch. The daemon commits its changes to a worktree branch — use that branch to see exactly what was done.
|
|
209
219
|
|
|
210
|
-
### Step 1:
|
|
220
|
+
### Step 1: Find the Worktree Branch
|
|
211
221
|
|
|
212
|
-
The daemon
|
|
222
|
+
The daemon creates a branch named `push-{number}-{suffix}`:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Get machine ID suffix
|
|
226
|
+
MACHINE_ID=$(cat ~/.config/push/machine_id 2>/dev/null)
|
|
227
|
+
SUFFIX=$(echo "$MACHINE_ID" | rev | cut -d'-' -f1 | rev | cut -c1-8)
|
|
228
|
+
TASK_NUM=<display_number>
|
|
229
|
+
BRANCH="push-${TASK_NUM}-${SUFFIX}"
|
|
230
|
+
|
|
231
|
+
# Check if branch exists and has commits
|
|
232
|
+
git log master..${BRANCH} --oneline 2>/dev/null
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Step 2: Get Semantic Summary from Session Transcript
|
|
236
|
+
|
|
237
|
+
Read the session transcript for context on *what* and *why* (reasoning, decisions):
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
SESSION_DIR="$HOME/.claude/projects/-Users-$(whoami)-projects-push-${TASK_NUM}-${SUFFIX}"
|
|
241
|
+
SESSION_ID=<session_id_from_task>
|
|
242
|
+
|
|
243
|
+
# Extract just the text reasoning (not file edits — we get those from git)
|
|
244
|
+
cat "${SESSION_DIR}/${SESSION_ID}.jsonl" 2>/dev/null | node -e "
|
|
245
|
+
const lines = [];
|
|
246
|
+
process.stdin.on('data', d => lines.push(d));
|
|
247
|
+
process.stdin.on('end', () => {
|
|
248
|
+
const entries = Buffer.concat(lines).toString().split('\n')
|
|
249
|
+
.filter(Boolean).map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
|
|
250
|
+
const texts = entries.filter(e => e.type === 'assistant')
|
|
251
|
+
.flatMap(a => (a.message?.content || []).filter(b => b.type === 'text' && b.text.trim()).map(b => b.text.trim()));
|
|
252
|
+
texts.forEach(t => console.log(t));
|
|
253
|
+
});
|
|
254
|
+
"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Step 3: Review Changes and Act
|
|
258
|
+
|
|
259
|
+
1. **Show the user** what the daemon did: semantic summary + `git diff master...${BRANCH}`
|
|
260
|
+
2. **If the branch has commits** (daemon committed):
|
|
261
|
+
- Show the diff and ask if user wants to cherry-pick/merge to current branch
|
|
262
|
+
- Use `git cherry-pick <commit>` or `git merge ${BRANCH}` as appropriate
|
|
263
|
+
3. **If the branch has NO commits** (daemon didn't commit — older daemon versions):
|
|
264
|
+
- Fall back to reading edits from the session transcript JSONL
|
|
265
|
+
4. **If work is incomplete**, continue from where the daemon left off using the context from the transcript and the branch state
|
|
266
|
+
|
|
267
|
+
## Live Session Status
|
|
268
|
+
|
|
269
|
+
When a task is currently running (daemon is actively working on it), read the live session transcript to show the user what's happening.
|
|
270
|
+
|
|
271
|
+
### Step 1: Locate the Live Session File
|
|
272
|
+
|
|
273
|
+
The daemon runs Claude in a git worktree. Find the active session:
|
|
213
274
|
|
|
214
275
|
```bash
|
|
215
276
|
# Get machine ID suffix for worktree name
|
|
@@ -219,18 +280,17 @@ TASK_NUM=<display_number>
|
|
|
219
280
|
|
|
220
281
|
# Session files are stored under ~/.claude/projects/ with path-encoded directory names
|
|
221
282
|
SESSION_DIR="$HOME/.claude/projects/-Users-$(whoami)-projects-push-${TASK_NUM}-${SUFFIX}"
|
|
222
|
-
SESSION_ID=<session_id_from_task>
|
|
223
283
|
|
|
224
|
-
#
|
|
225
|
-
ls "${SESSION_DIR}
|
|
284
|
+
# Find the most recent .jsonl file (the active session)
|
|
285
|
+
ls -t "${SESSION_DIR}"/*.jsonl 2>/dev/null | head -1
|
|
226
286
|
```
|
|
227
287
|
|
|
228
|
-
### Step 2: Extract
|
|
288
|
+
### Step 2: Extract Recent Activity
|
|
229
289
|
|
|
230
|
-
Read the JSONL transcript
|
|
290
|
+
Read the last portion of the JSONL transcript to see what Claude is currently doing:
|
|
231
291
|
|
|
232
292
|
```bash
|
|
233
|
-
|
|
293
|
+
tail -100 "<session_file>" | node -e "
|
|
234
294
|
const lines = [];
|
|
235
295
|
process.stdin.on('data', d => lines.push(d));
|
|
236
296
|
process.stdin.on('end', () => {
|
|
@@ -239,38 +299,43 @@ process.stdin.on('end', () => {
|
|
|
239
299
|
|
|
240
300
|
const assistantMsgs = entries.filter(e => e.type === 'assistant');
|
|
241
301
|
const edits = [];
|
|
302
|
+
const reads = [];
|
|
242
303
|
const texts = [];
|
|
243
304
|
|
|
244
305
|
assistantMsgs.forEach(a => {
|
|
245
306
|
(a.message?.content || []).forEach(b => {
|
|
246
307
|
if (b.type === 'text' && b.text.trim()) texts.push(b.text.trim());
|
|
247
|
-
if (b.type === 'tool_use'
|
|
248
|
-
edits.push(b.input?.file_path);
|
|
308
|
+
if (b.type === 'tool_use') {
|
|
309
|
+
if (b.name === 'Edit' || b.name === 'Write') edits.push(b.input?.file_path);
|
|
310
|
+
if (b.name === 'Read') reads.push(b.input?.file_path);
|
|
311
|
+
}
|
|
249
312
|
});
|
|
250
313
|
});
|
|
251
314
|
|
|
252
|
-
console.log('
|
|
253
|
-
console.log('
|
|
254
|
-
|
|
255
|
-
console.log(
|
|
315
|
+
console.log('FILES_READ:', JSON.stringify([...new Set(reads)].slice(-10)));
|
|
316
|
+
console.log('FILES_EDITED:', JSON.stringify([...new Set(edits)]));
|
|
317
|
+
console.log('---RECENT_ACTIVITY---');
|
|
318
|
+
texts.slice(-5).forEach(t => console.log(t.slice(0, 200)));
|
|
319
|
+
console.log('---END---');
|
|
256
320
|
});
|
|
257
321
|
"
|
|
258
322
|
```
|
|
259
323
|
|
|
260
|
-
### Step 3: Present
|
|
324
|
+
### Step 3: Present Status to User
|
|
261
325
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
326
|
+
Show a concise summary:
|
|
327
|
+
1. "The daemon is currently working on this task"
|
|
328
|
+
2. Files it has read so far
|
|
329
|
+
3. Files it has edited so far
|
|
330
|
+
4. Its most recent reasoning/activity (last few text messages)
|
|
331
|
+
5. "Check back in a few minutes, or run `/push-todo <number>` again for an update"
|
|
266
332
|
|
|
267
|
-
|
|
333
|
+
Do NOT offer to start working on the task — the daemon is already handling it.
|
|
268
334
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
This launches a full interactive Claude Code session with the daemon's complete conversation history.
|
|
335
|
+
### Fallback
|
|
336
|
+
|
|
337
|
+
If the session file cannot be found (daemon just started, no output yet):
|
|
338
|
+
- Tell the user: "The daemon just started working on this task. Run `/push-todo <number>` again in a minute for a progress update."
|
|
274
339
|
|
|
275
340
|
## CLI Reference
|
|
276
341
|
|
package/lib/daemon.js
CHANGED
|
@@ -780,9 +780,10 @@ function executeTask(task) {
|
|
|
780
780
|
|
|
781
781
|
${content}
|
|
782
782
|
|
|
783
|
-
IMPORTANT:
|
|
784
|
-
|
|
785
|
-
|
|
783
|
+
IMPORTANT:
|
|
784
|
+
1. If you need to understand the codebase, start by reading the CLAUDE.md file if it exists.
|
|
785
|
+
2. ALWAYS commit your changes before finishing. Use a descriptive commit message summarizing what you did. This is critical — uncommitted changes will be lost when the worktree is cleaned up.
|
|
786
|
+
3. When you're done, the SessionEnd hook will automatically report completion to Supabase.`;
|
|
786
787
|
|
|
787
788
|
// Update status to running
|
|
788
789
|
updateTaskStatus(displayNumber, 'running');
|