sticky-note-cli 3.1.37 → 3.1.39

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
@@ -260,6 +260,21 @@ function readJsonSafe(filePath, fallback) {
260
260
  }
261
261
  }
262
262
 
263
+ function readEnvSticky(cwd) {
264
+ try {
265
+ const raw = fs.readFileSync(path.join(cwd, ".env.sticky"), "utf-8");
266
+ let url = "", key = "";
267
+ for (const line of raw.split(/\r?\n/)) {
268
+ const t = line.trim();
269
+ if (t.startsWith("STICKY_URL=")) url = t.slice("STICKY_URL=".length).trim();
270
+ else if (t.startsWith("STICKY_API_KEY=")) key = t.slice("STICKY_API_KEY=".length).trim();
271
+ }
272
+ return { url, key };
273
+ } catch (_) {
274
+ return { url: "", key: "" };
275
+ }
276
+ }
277
+
263
278
  function parseIntOr(str, fallback) {
264
279
  const n = parseInt(str, 10);
265
280
  return Number.isNaN(n) ? fallback : n;
@@ -609,25 +624,22 @@ async function cmdInit() {
609
624
  print(" [ERR] Not a git repository. Run `git init` first.");
610
625
  process.exit(1);
611
626
  }
612
- print(" [OK] Git repository detected");
627
+ // Resolve git root and chdir there so init works from any subdirectory
628
+ const repoRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
629
+ if (repoRoot !== process.cwd()) {
630
+ process.chdir(repoRoot);
631
+ print(` [OK] Git repository detected (running from root: ${repoRoot})`);
632
+ } else {
633
+ print(" [OK] Git repository detected");
634
+ }
613
635
  print("");
614
636
 
615
637
  // Read existing sticky-note-config.json for teammate flow (cloud URL pre-set via git)
616
638
  const existingConfigPath = path.join(process.cwd(), ".sticky-note", "sticky-note-config.json");
617
639
  const existingConfig = readJsonSafe(existingConfigPath, {});
618
- // Also check .env.sticky as fallback — handles case where URL was set locally but never
619
- // committed to the config (e.g. set up via wrangler deploy rather than `init --v3`)
620
- let envStickyUrlFallback = "";
621
- try {
622
- const envStickyRaw = fs.readFileSync(path.join(process.cwd(), ".env.sticky"), "utf-8");
623
- for (const line of envStickyRaw.split(/\r?\n/)) {
624
- if (line.trim().startsWith("STICKY_URL=")) {
625
- envStickyUrlFallback = line.trim().slice("STICKY_URL=".length).trim();
626
- break;
627
- }
628
- }
629
- } catch (_) { /* no .env.sticky yet */ }
630
- const configStickyUrl = existingConfig.sticky_url || envStickyUrlFallback || "";
640
+ // Fall back to .env.sticky when sticky_url isn't committed yet — lets the URL
641
+ // get written into config on next init so teammates see the teammate flow on pull.
642
+ const configStickyUrl = existingConfig.sticky_url || readEnvSticky(process.cwd()).url;
631
643
 
632
644
  // Auto-detect MCP servers and skills
633
645
  print(" Scanning for existing configuration...");
@@ -996,7 +1008,8 @@ async function cmdInit() {
996
1008
  existing.inject_token_budget = injectTokenBudgetResolved;
997
1009
  existing.hook_version = VERSION;
998
1010
  existing.min_version = bumpMinVersion(existing.min_version, VERSION);
999
- if (cloudProvisionedUrl || configStickyUrl) existing.sticky_url = cloudProvisionedUrl || configStickyUrl;
1011
+ if (cloudProvisionedUrl) existing.sticky_url = cloudProvisionedUrl;
1012
+ else if (configStickyUrl && !existing.sticky_url) existing.sticky_url = configStickyUrl;
1000
1013
  // Enable auto_push when cloud is configured (if not already explicitly set)
1001
1014
  if ((cloudProvisionedUrl || configStickyUrl) && existing.auto_push === false) {
1002
1015
  existing.auto_push = true;
@@ -1741,17 +1754,9 @@ function cmdStatus() {
1741
1754
  // V3: Cloud backend health
1742
1755
  const envStickyPath = path.join(process.cwd(), ".env.sticky");
1743
1756
  print("\n Cloud Backend (V3):");
1744
- if (fs.existsSync(envStickyPath)) {
1745
- try {
1746
- const envRaw = fs.readFileSync(envStickyPath, "utf-8");
1747
- let stickyUrl = "";
1748
- for (const line of envRaw.split(/\r?\n/)) {
1749
- const trimmed = line.trim();
1750
- if (trimmed.startsWith("STICKY_URL=")) {
1751
- stickyUrl = trimmed.slice("STICKY_URL=".length).trim();
1752
- }
1753
- }
1754
- if (stickyUrl) {
1757
+ {
1758
+ const { url: stickyUrl } = readEnvSticky(process.cwd());
1759
+ if (stickyUrl) {
1755
1760
  print(` [OK] .env.sticky found (${stickyUrl})`);
1756
1761
  try {
1757
1762
  const http = require(stickyUrl.startsWith("https") ? "https" : "http");
@@ -1798,14 +1803,12 @@ function cmdStatus() {
1798
1803
  } catch (_) {
1799
1804
  print(` [ERR] Backend health check failed`);
1800
1805
  }
1801
- } else {
1802
- print(" [--] .env.sticky found but STICKY_URL not set");
1803
- }
1804
- } catch (_) {
1805
- print(" [ERR] .env.sticky unreadable");
1806
+ } else {
1807
+ const exists = fs.existsSync(envStickyPath);
1808
+ print(exists
1809
+ ? " [--] .env.sticky found but STICKY_URL not set"
1810
+ : " [--] No .env.sticky (local-only mode, V2.5 compatible)");
1806
1811
  }
1807
- } else {
1808
- print(" [--] No .env.sticky (local-only mode, V2.5 compatible)");
1809
1812
  }
1810
1813
 
1811
1814
  // V2.5: Attribution engine health
@@ -3567,14 +3570,10 @@ async function cmdMigrateToCloud() {
3567
3570
  // Try .env.sticky
3568
3571
  let envUrl = stickyUrl;
3569
3572
  let envKey = stickyApiKey;
3570
- const envStickyPath = path.join(process.cwd(), ".env.sticky");
3571
- if (!envUrl && fs.existsSync(envStickyPath)) {
3572
- const raw = fs.readFileSync(envStickyPath, "utf-8");
3573
- for (const line of raw.split(/\r?\n/)) {
3574
- const trimmed = line.trim();
3575
- if (trimmed.startsWith("STICKY_URL=")) envUrl = trimmed.slice("STICKY_URL=".length);
3576
- if (trimmed.startsWith("STICKY_API_KEY=")) envKey = trimmed.slice("STICKY_API_KEY=".length);
3577
- }
3573
+ if (!envUrl) {
3574
+ const env = readEnvSticky(process.cwd());
3575
+ envUrl = env.url;
3576
+ envKey = envKey || env.key;
3578
3577
  }
3579
3578
 
3580
3579
  if (!envUrl) {
@@ -3713,14 +3712,10 @@ async function _cmdMcpServerInline() {
3713
3712
  // Try .env.sticky
3714
3713
  let envUrl = stickyUrl;
3715
3714
  let envKey = stickyApiKey;
3716
- const envStickyPath = path.join(process.cwd(), ".env.sticky");
3717
- if (!envUrl && fs.existsSync(envStickyPath)) {
3718
- const raw = fs.readFileSync(envStickyPath, "utf-8");
3719
- for (const line of raw.split(/\r?\n/)) {
3720
- const trimmed = line.trim();
3721
- if (trimmed.startsWith("STICKY_URL=")) envUrl = trimmed.slice("STICKY_URL=".length);
3722
- if (trimmed.startsWith("STICKY_API_KEY=")) envKey = trimmed.slice("STICKY_API_KEY=".length);
3723
- }
3715
+ if (!envUrl) {
3716
+ const env = readEnvSticky(process.cwd());
3717
+ envUrl = env.url;
3718
+ envKey = envKey || env.key;
3724
3719
  }
3725
3720
 
3726
3721
  // Detect project
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sticky-note-cli",
3
- "version": "3.1.37",
3
+ "version": "3.1.39",
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": {
@@ -1,3 +0,0 @@
1
- {
2
- "hooks": {}
3
- }