@masslessai/push-todo 3.1.0 → 3.2.1

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,5 +1,5 @@
1
1
  {
2
2
  "name": "push-todo",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Voice tasks from Push iOS app"
5
5
  }
package/lib/cli.js CHANGED
@@ -15,7 +15,7 @@ import { ensureDaemonRunning, getDaemonStatus, startDaemon, stopDaemon } from '.
15
15
  import { getScreenshotPath, screenshotExists, openScreenshot } from './utils/screenshots.js';
16
16
  import { bold, red, cyan, dim, green } from './utils/colors.js';
17
17
 
18
- const VERSION = '3.1.0';
18
+ const VERSION = '3.2.1';
19
19
 
20
20
  const HELP_TEXT = `
21
21
  ${bold('push-todo')} - Voice tasks from Push iOS app for Claude Code
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masslessai/push-todo",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Voice tasks from Push iOS app for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,11 +2,14 @@
2
2
  /**
3
3
  * Post-install script for Push CLI.
4
4
  *
5
- * 1. Sets up Claude Code plugin symlink
6
- * 2. Downloads the native keychain helper binary for macOS
5
+ * Sets up integrations for ALL detected AI coding clients:
6
+ * 1. Claude Code - symlink to ~/.claude/plugins/
7
+ * 2. OpenAI Codex - AGENTS.md in ~/.codex/
8
+ * 3. Clawdbot - SKILL.md in ~/.clawdbot/skills/
9
+ * 4. Downloads native keychain helper binary (macOS)
7
10
  */
8
11
 
9
- import { createWriteStream, existsSync, mkdirSync, unlinkSync, readFileSync, symlinkSync, lstatSync, readlinkSync, rmSync } from 'fs';
12
+ import { createWriteStream, existsSync, mkdirSync, unlinkSync, readFileSync, writeFileSync, symlinkSync, lstatSync, readlinkSync, rmSync, appendFileSync } from 'fs';
10
13
  import { chmod, stat } from 'fs/promises';
11
14
  import { pipeline } from 'stream/promises';
12
15
  import { join, dirname } from 'path';
@@ -19,15 +22,24 @@ const __dirname = dirname(__filename);
19
22
  // Package root (one level up from scripts/)
20
23
  const PACKAGE_ROOT = join(__dirname, '..');
21
24
 
22
- // Claude Code plugin locations
25
+ // Claude Code locations
23
26
  const CLAUDE_DIR = join(homedir(), '.claude');
24
27
  const PLUGIN_DIR = join(CLAUDE_DIR, 'plugins');
25
28
  const PLUGIN_LINK = join(PLUGIN_DIR, 'push-todo');
26
-
27
- // Legacy location (for migration)
28
29
  const LEGACY_SKILL_DIR = join(CLAUDE_DIR, 'skills');
29
30
  const LEGACY_SKILL_LINK = join(LEGACY_SKILL_DIR, 'push-todo');
30
31
 
32
+ // OpenAI Codex locations
33
+ const CODEX_DIR = join(homedir(), '.codex');
34
+ const CODEX_SKILL_DIR = join(CODEX_DIR, 'skills', 'push-todo');
35
+ const CODEX_SKILL_FILE = join(CODEX_SKILL_DIR, 'SKILL.md');
36
+ const CODEX_AGENTS_FILE = join(CODEX_DIR, 'AGENTS.md');
37
+
38
+ // Clawdbot locations
39
+ const CLAWDBOT_DIR = join(homedir(), '.clawdbot');
40
+ const CLAWDBOT_SKILL_DIR = join(CLAWDBOT_DIR, 'skills', 'push-todo');
41
+ const CLAWDBOT_SKILL_FILE = join(CLAWDBOT_SKILL_DIR, 'SKILL.md');
42
+
31
43
  const BINARY_NAME = 'push-keychain-helper';
32
44
  const BINARY_DIR = join(__dirname, '../bin');
33
45
  const BINARY_PATH = join(BINARY_DIR, BINARY_NAME);
@@ -130,6 +142,189 @@ function migrateFromPython() {
130
142
  }
131
143
  }
132
144
 
145
+ /**
146
+ * Set up OpenAI Codex integration.
147
+ * Creates ~/.codex/skills/push-todo/SKILL.md and updates AGENTS.md
148
+ *
149
+ * @returns {boolean} True if Codex was detected and set up
150
+ */
151
+ function setupCodex() {
152
+ // Only set up if Codex directory exists (user has Codex installed)
153
+ if (!existsSync(CODEX_DIR)) {
154
+ return false;
155
+ }
156
+
157
+ console.log('[push-todo] Detected OpenAI Codex installation');
158
+
159
+ // Skill file content
160
+ const SKILL_CONTENT = `# Push Tasks Skill
161
+
162
+ This skill retrieves and processes tasks sent from the Push iOS app.
163
+
164
+ ## Activation
165
+
166
+ This skill activates when the user:
167
+ - Says "push-todo", "push todo", "push tasks", or "tasks from push"
168
+ - Runs \`$push-todo\` command
169
+ - Mentions "tasks from iPhone" or "mobile tasks"
170
+ - Asks about "pending tasks" or "voice tasks"
171
+
172
+ ## Commands
173
+
174
+ Run these in the terminal:
175
+
176
+ | Command | Description |
177
+ |---------|-------------|
178
+ | \`push-todo\` | List active tasks |
179
+ | \`push-todo 427\` | Show task #427 |
180
+ | \`push-todo connect\` | Connect/fix issues |
181
+ | \`push-todo search "query"\` | Search tasks |
182
+ | \`push-todo --help\` | All options |
183
+
184
+ ## Instructions
185
+
186
+ When this skill is activated:
187
+
188
+ 1. **Check connection** - If user hasn't set up, run:
189
+ \`\`\`bash
190
+ push-todo connect
191
+ \`\`\`
192
+
193
+ 2. **Fetch tasks** - List available tasks:
194
+ \`\`\`bash
195
+ push-todo
196
+ \`\`\`
197
+
198
+ 3. **Work on specific task** - Get task details:
199
+ \`\`\`bash
200
+ push-todo 427
201
+ \`\`\`
202
+
203
+ 4. **Present the task** to the user with a brief summary and offer to help implement it.
204
+ `;
205
+
206
+ // AGENTS.md bootstrap content
207
+ const AGENTS_SECTION = `
208
+ ## Push Tasks Integration
209
+
210
+ At the start of each session, check for pending tasks from the Push iOS app:
211
+
212
+ 1. Run this command silently:
213
+ \`\`\`bash
214
+ push-todo --json 2>/dev/null | head -1
215
+ \`\`\`
216
+
217
+ 2. If tasks exist, inform the user:
218
+ "You have X task(s) from Push. Type $push-todo to see them."
219
+
220
+ 3. If no output or error, proceed normally without mentioning Push.
221
+ `;
222
+
223
+ try {
224
+ // Create skill directory and SKILL.md
225
+ mkdirSync(CODEX_SKILL_DIR, { recursive: true });
226
+ writeFileSync(CODEX_SKILL_FILE, SKILL_CONTENT);
227
+ console.log('[push-todo] Codex: Created skills/push-todo/SKILL.md');
228
+
229
+ // Update AGENTS.md for session-start bootstrap
230
+ if (existsSync(CODEX_AGENTS_FILE)) {
231
+ const content = readFileSync(CODEX_AGENTS_FILE, 'utf8');
232
+ if (content.includes('Push Tasks Integration')) {
233
+ // Update existing section (replace old Python references)
234
+ const updated = content.replace(
235
+ /## Push Tasks Integration[\s\S]*?(?=\n## |$)/,
236
+ AGENTS_SECTION.trim() + '\n\n'
237
+ );
238
+ writeFileSync(CODEX_AGENTS_FILE, updated);
239
+ console.log('[push-todo] Codex: Updated AGENTS.md');
240
+ } else {
241
+ appendFileSync(CODEX_AGENTS_FILE, AGENTS_SECTION);
242
+ console.log('[push-todo] Codex: Added to AGENTS.md');
243
+ }
244
+ } else {
245
+ writeFileSync(CODEX_AGENTS_FILE, AGENTS_SECTION.trim() + '\n');
246
+ console.log('[push-todo] Codex: Created AGENTS.md');
247
+ }
248
+
249
+ return true;
250
+ } catch (error) {
251
+ console.log(`[push-todo] Codex: Setup failed: ${error.message}`);
252
+ return false;
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Set up Clawdbot integration.
258
+ * Creates ~/.clawdbot/skills/push-todo/SKILL.md
259
+ *
260
+ * @returns {boolean} True if Clawdbot was detected and set up
261
+ */
262
+ function setupClawdbot() {
263
+ // Only set up if Clawdbot directory exists (user has Clawdbot installed)
264
+ if (!existsSync(CLAWDBOT_DIR)) {
265
+ return false;
266
+ }
267
+
268
+ console.log('[push-todo] Detected Clawdbot installation');
269
+
270
+ const SKILL_CONTENT = `# Push Tasks
271
+
272
+ Voice tasks captured on iPhone, ready to work on.
273
+
274
+ ## Commands
275
+
276
+ Run these in the terminal:
277
+
278
+ | Command | Description |
279
+ |---------|-------------|
280
+ | \`push-todo\` | List active tasks |
281
+ | \`push-todo 427\` | Show task #427 |
282
+ | \`push-todo connect\` | Connect/fix issues |
283
+ | \`push-todo search "query"\` | Search tasks |
284
+ | \`push-todo --help\` | All options |
285
+
286
+ ## Quick Start
287
+
288
+ If not connected yet, run:
289
+ \`\`\`bash
290
+ push-todo connect
291
+ \`\`\`
292
+
293
+ To see tasks:
294
+ \`\`\`bash
295
+ push-todo
296
+ \`\`\`
297
+
298
+ To work on a specific task:
299
+ \`\`\`bash
300
+ push-todo 427
301
+ \`\`\`
302
+
303
+ ## Session Start
304
+
305
+ At the start of each session, check for tasks:
306
+ \`\`\`bash
307
+ push-todo --json 2>/dev/null | head -1
308
+ \`\`\`
309
+ If tasks exist, inform the user.
310
+ `;
311
+
312
+ try {
313
+ mkdirSync(CLAWDBOT_SKILL_DIR, { recursive: true });
314
+
315
+ if (existsSync(CLAWDBOT_SKILL_FILE)) {
316
+ console.log('[push-todo] Clawdbot: SKILL.md already exists, updating...');
317
+ }
318
+
319
+ writeFileSync(CLAWDBOT_SKILL_FILE, SKILL_CONTENT);
320
+ console.log('[push-todo] Clawdbot: Created skills/push-todo/SKILL.md');
321
+ return true;
322
+ } catch (error) {
323
+ console.log(`[push-todo] Clawdbot: Could not set up SKILL.md: ${error.message}`);
324
+ return false;
325
+ }
326
+ }
327
+
133
328
  /**
134
329
  * Download a file from URL to destination.
135
330
  *
@@ -184,35 +379,66 @@ async function main() {
184
379
 
185
380
  // Step 3: Set up Claude Code plugin symlink
186
381
  console.log('[push-todo] Setting up Claude Code plugin...');
187
- const pluginSuccess = setupClaudePlugin();
382
+ const claudeSuccess = setupClaudePlugin();
188
383
  console.log('');
189
384
 
190
- // Step 4: Download native binary (macOS only)
385
+ // Step 4: Set up OpenAI Codex (if installed)
386
+ const codexSuccess = setupCodex();
387
+ if (codexSuccess) console.log('');
388
+
389
+ // Step 5: Set up Clawdbot (if installed)
390
+ const clawdbotSuccess = setupClawdbot();
391
+ if (clawdbotSuccess) console.log('');
392
+
393
+ // Track which clients were set up
394
+ const clients = [];
395
+ if (claudeSuccess) clients.push('Claude Code');
396
+ if (codexSuccess) clients.push('OpenAI Codex');
397
+ if (clawdbotSuccess) clients.push('Clawdbot');
398
+
399
+ // Step 6: Download native binary (macOS only)
191
400
  if (platform() !== 'darwin') {
192
401
  console.log('[push-todo] Skipping native binary (macOS only)');
193
402
  console.log('[push-todo] E2EE features will not be available.');
194
403
  console.log('');
195
- console.log('[push-todo] Installation complete.');
196
- if (pluginSuccess) {
197
- console.log('[push-todo] You can now use /push-todo in Claude Code!');
404
+ console.log('[push-todo] Installation complete!');
405
+ if (clients.length > 0) {
406
+ console.log(`[push-todo] Configured for: ${clients.join(', ')}`);
198
407
  }
199
408
  return;
200
409
  }
201
410
 
202
411
  // Check if binary already exists and is valid
412
+ let binaryExists = false;
203
413
  if (existsSync(BINARY_PATH)) {
204
414
  try {
205
415
  const stats = await stat(BINARY_PATH);
206
416
  if (stats.size > 0) {
207
417
  console.log('[push-todo] Native binary already installed.');
208
- console.log('[push-todo] Installation complete.');
209
- return;
418
+ binaryExists = true;
210
419
  }
211
420
  } catch {
212
421
  // Continue to download
213
422
  }
214
423
  }
215
424
 
425
+ if (binaryExists) {
426
+ // Skip download, show summary
427
+ console.log('');
428
+ console.log('[push-todo] Installation complete!');
429
+ if (clients.length > 0) {
430
+ console.log(`[push-todo] Configured for: ${clients.join(', ')}`);
431
+ }
432
+ console.log('');
433
+ console.log('[push-todo] Quick start:');
434
+ console.log('[push-todo] push-todo connect Set up authentication');
435
+ console.log('[push-todo] push-todo List your tasks');
436
+ if (claudeSuccess) console.log('[push-todo] /push-todo Use in Claude Code');
437
+ if (codexSuccess) console.log('[push-todo] $push-todo Use in OpenAI Codex');
438
+ if (clawdbotSuccess) console.log('[push-todo] /push-todo Use in Clawdbot');
439
+ return;
440
+ }
441
+
216
442
  // Determine architecture
217
443
  const archType = arch();
218
444
  const url = archType === 'arm64' ? BINARY_URL : BINARY_URL_X64;
@@ -233,11 +459,22 @@ async function main() {
233
459
 
234
460
  console.log('');
235
461
  console.log('[push-todo] Installation complete!');
462
+ if (clients.length > 0) {
463
+ console.log(`[push-todo] Configured for: ${clients.join(', ')}`);
464
+ }
236
465
  console.log('');
237
466
  console.log('[push-todo] Quick start:');
238
467
  console.log('[push-todo] push-todo connect Set up authentication');
239
468
  console.log('[push-todo] push-todo List your tasks');
240
- console.log('[push-todo] /push-todo Use in Claude Code');
469
+ if (claudeSuccess) {
470
+ console.log('[push-todo] /push-todo Use in Claude Code');
471
+ }
472
+ if (codexSuccess) {
473
+ console.log('[push-todo] $push-todo Use in OpenAI Codex');
474
+ }
475
+ if (clawdbotSuccess) {
476
+ console.log('[push-todo] /push-todo Use in Clawdbot');
477
+ }
241
478
  }
242
479
 
243
480
  main().catch(error => {