skalpel 4.0.5 → 4.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/postinstall.mjs +18 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skalpel",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
4
4
  "description": "Behavioral graph for AI-assisted coding — learns how you work and steers Claude Code + Codex in real time.",
5
5
  "type": "module",
6
6
  "bin": {
package/postinstall.mjs CHANGED
@@ -57,8 +57,26 @@ function stageStatusline() {
57
57
  }
58
58
  }
59
59
 
60
+ // If this postinstall ran under `sudo npm install -g`, we're root but a REAL user invoked it — so
61
+ // anything we just created in their HOME (the staged ~/.skalpel) is root-owned, a landmine for the
62
+ // later non-root `skalpel` (that's Ryaan's EACCES on copyfile into ~/.skalpel/hooks). Chown it back to
63
+ // the invoking user so the sudo install path isn't left broken.
64
+ function fixSudoOwnership() {
65
+ try {
66
+ if (process.platform === "win32") return; // no uid / sudo model
67
+ if (typeof process.getuid !== "function" || process.getuid() !== 0) return; // not root — nothing to undo
68
+ const uid = process.env.SUDO_UID;
69
+ if (!uid) return; // genuinely root (not via sudo) — don't touch their files
70
+ const gid = process.env.SUDO_GID || uid;
71
+ spawnSync("chown", ["-R", `${uid}:${gid}`, join(homedir(), ".skalpel")], q);
72
+ } catch {
73
+ /* best-effort — worst case the user runs `sudo chown -R $(whoami) ~/.skalpel` themselves */
74
+ }
75
+ }
76
+
60
77
  retireLegacyDaemon();
61
78
  stageStatusline();
79
+ fixSudoOwnership();
62
80
 
63
81
  // A quiet nudge — the real onboarding (Google sign-in → build graph → insights) runs on `skalpel`.
64
82
  if (process.stdout.isTTY && !process.env.CI) {