sticky-note-cli 2.7.3 → 2.8.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.
package/bin/cli.js CHANGED
@@ -716,6 +716,18 @@ async function cmdInit() {
716
716
  print(" ⏭️ Could not set git alias (non-fatal)");
717
717
  }
718
718
 
719
+ // Add git alias for safe pull with auto-sync
720
+ try {
721
+ const spullAlias = '!f() { npx sticky-note pull "$@"; }; f';
722
+ execFileSync("git", ["config", "alias.spull", spullAlias], {
723
+ cwd: process.cwd(),
724
+ stdio: ["pipe", "pipe", "pipe"],
725
+ });
726
+ print(" [OK] git alias: git spull (auto-sync + pull)");
727
+ } catch (_) {
728
+ print(" ⏭️ Could not set git spull alias (non-fatal)");
729
+ }
730
+
719
731
  // Deploy AI instruction files (CLAUDE.md + .github/copilot-instructions.md)
720
732
  const claudeMdDest = path.join(process.cwd(), "CLAUDE.md");
721
733
  if (!fs.existsSync(claudeMdDest)) {
@@ -2477,6 +2489,50 @@ function cmdSync() {
2477
2489
  print("");
2478
2490
  }
2479
2491
 
2492
+ // ──────────────────────────────────────────────
2493
+ // PULL command — auto-sync + git pull
2494
+ // ──────────────────────────────────────────────
2495
+
2496
+ function cmdPull() {
2497
+ const args = process.argv.slice(3);
2498
+ const stickyDir = path.join(process.cwd(), ".sticky-note");
2499
+
2500
+ // Step 1: Sync .sticky-note/ changes if any
2501
+ if (fs.existsSync(stickyDir)) {
2502
+ try {
2503
+ const status = execSync(
2504
+ 'git status --porcelain -- ".sticky-note/sticky-note.json" ".sticky-note/audit/" ".sticky-note/presence/"',
2505
+ { encoding: "utf-8", cwd: process.cwd() }
2506
+ ).trim();
2507
+ if (status) {
2508
+ const guardPath = path.join(stickyDir, ".sticky-syncing");
2509
+ fs.writeFileSync(guardPath, process.pid.toString(), "utf-8");
2510
+ try {
2511
+ execFileSync("git", [
2512
+ "add", "--", ".sticky-note/sticky-note.json",
2513
+ ".sticky-note/audit/", ".sticky-note/presence/"
2514
+ ], { cwd: process.cwd(), timeout: 10000, stdio: ["pipe", "pipe", "pipe"] });
2515
+ execFileSync("git", [
2516
+ "commit", "--no-verify", "-m", "chore(sticky-note): sync thread data"
2517
+ ], { cwd: process.cwd(), timeout: 15000, stdio: ["pipe", "pipe", "pipe"] });
2518
+ print(" ✅ Auto-synced .sticky-note/ before pull");
2519
+ } finally {
2520
+ try { fs.unlinkSync(guardPath); } catch (_) {}
2521
+ }
2522
+ }
2523
+ } catch (_) {
2524
+ // Non-fatal — proceed with pull even if sync fails
2525
+ }
2526
+ }
2527
+
2528
+ // Step 2: Run git pull with any extra args
2529
+ try {
2530
+ execFileSync("git", ["pull", ...args], { stdio: "inherit", cwd: process.cwd() });
2531
+ } catch (err) {
2532
+ process.exit(err.status || 1);
2533
+ }
2534
+ }
2535
+
2480
2536
  // MCP-SERVER command — launch the stdio MCP server
2481
2537
  function cmdMcpServer() {
2482
2538
  const mcpServerPath = path.join(__dirname, "mcp-server.js");
@@ -3064,6 +3120,9 @@ async function main() {
3064
3120
  case "sync":
3065
3121
  cmdSync();
3066
3122
  break;
3123
+ case "pull":
3124
+ cmdPull();
3125
+ break;
3067
3126
  case "bootstrap":
3068
3127
  await cmdBootstrap();
3069
3128
  break;
@@ -3099,6 +3158,7 @@ async function main() {
3099
3158
  print(" overlap Detect file overlaps with open/stuck threads");
3100
3159
  print(" claim Claim ownership of files you're working on (--list, --clear)");
3101
3160
  print(" sync Commit .sticky-note/ changes to git (--push to also push)");
3161
+ print(" pull Auto-sync .sticky-note/ then git pull (alias: git spull)");
3102
3162
  print(" bootstrap Provision MCP servers with secrets from manifest");
3103
3163
  print(" env Environment management (status, add-server, add-plugin)");
3104
3164
  print(" mcp-server Launch the sticky-note MCP server (stdio JSON-RPC)");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sticky-note-cli",
3
- "version": "2.7.3",
3
+ "version": "2.8.0",
4
4
  "description": "Human-to-human handoff for AI coding assistants. Git-backed shared memory for Claude Code and Copilot CLI.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -66,6 +66,7 @@ const {
66
66
  getMemoryPath,
67
67
  loadJson,
68
68
  normalizeSep,
69
+ syncStickyNote,
69
70
  } = utils;
70
71
 
71
72
  // ── File path extraction from tool input ──────────────────
@@ -189,6 +190,17 @@ function main() {
189
190
 
190
191
  const sessionId = getSessionId(hookInput);
191
192
 
193
+ // ── Auto-sync before git pull/merge/rebase ──
194
+ // Prevents "local changes would be overwritten" errors for .sticky-note/ files
195
+ const toolName = (hookInput.tool_name || hookInput.toolName || "").toLowerCase();
196
+ if (toolName === "bash" || toolName === "shell" || toolName === "command") {
197
+ const toolInput = hookInput.tool_input || hookInput.input || hookInput.toolArgs || {};
198
+ const cmd = typeof toolInput === "string" ? toolInput : (toolInput.command || "");
199
+ if (/\bgit\s+(pull|merge|rebase|fetch)\b/.test(cmd)) {
200
+ try { syncStickyNote({}); } catch (_) {}
201
+ }
202
+ }
203
+
192
204
  // ── Overlap deny gate (Copilot CLI only) ──
193
205
  // Detect overlaps and deny on first tool call, keyed by COPILOT_LOADER_PID.
194
206
  const denyResult = _checkOverlapsAndDeny();