@pushary/agent-hooks 0.18.1 → 0.18.2
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/dist/bin/pushary-doctor.js +12 -2
- package/dist/bin/pushary-setup.js +28 -2
- package/package.json +1 -1
|
@@ -189,8 +189,18 @@ var main = async () => {
|
|
|
189
189
|
}
|
|
190
190
|
const cursorPluginDir = join(homedir(), ".cursor", "plugins", "local", "pushary");
|
|
191
191
|
if (existsSync(cursorPluginDir)) {
|
|
192
|
-
const
|
|
193
|
-
|
|
192
|
+
const cursorUserHooks = join(homedir(), ".cursor", "hooks.json");
|
|
193
|
+
const userHooks = readJson(cursorUserHooks);
|
|
194
|
+
const gateEntry = userHooks.hooks?.beforeShellExecution?.find(
|
|
195
|
+
(h) => String(h.command ?? "").includes("pushary-gate")
|
|
196
|
+
);
|
|
197
|
+
if (!gateEntry) {
|
|
198
|
+
check(false, "Cursor: permission gate registered", "no Pushary gate in ~/.cursor/hooks.json \u2014 re-run setup (a plugin-only hooks.json is never read by Cursor)");
|
|
199
|
+
} else {
|
|
200
|
+
const scriptPath = String(gateEntry.command).match(/"([^"]+)"/)?.[1] ?? "";
|
|
201
|
+
const resolves = scriptPath ? existsSync(scriptPath) : false;
|
|
202
|
+
check(resolves, "Cursor: permission gate registered", resolves ? `~/.cursor/hooks.json \u2192 ${scriptPath}` : `gate script not found: ${scriptPath || gateEntry.command} \u2014 re-run setup`);
|
|
203
|
+
}
|
|
194
204
|
const cursorMcp = readJson(join(cursorPluginDir, "mcp.json"));
|
|
195
205
|
const cursorServers = cursorMcp?.mcpServers ?? {};
|
|
196
206
|
const cursorAuth = cursorServers.pushary?.headers?.Authorization;
|
|
@@ -296,6 +296,7 @@ var connectViaAppPairing = async () => {
|
|
|
296
296
|
var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
|
|
297
297
|
var CLAUDE_JSON = join(homedir(), ".claude.json");
|
|
298
298
|
var CURSOR_PLUGIN_DIR = join(homedir(), ".cursor", "plugins", "local", "pushary");
|
|
299
|
+
var CURSOR_USER_HOOKS = join(homedir(), ".cursor", "hooks.json");
|
|
299
300
|
var CLAUDE_SKILL_DIR = join(homedir(), ".claude", "skills", "pushary");
|
|
300
301
|
var CODEX_HOME = process.env.CODEX_HOME?.trim() || join(homedir(), ".codex");
|
|
301
302
|
var CODEX_SKILL_DIR = join(CODEX_HOME, "skills", "pushary");
|
|
@@ -697,6 +698,28 @@ var resolveBundledPlugin = () => {
|
|
|
697
698
|
];
|
|
698
699
|
return candidates.find((p) => existsSync(join(p, ".cursor-plugin", "plugin.json"))) ?? null;
|
|
699
700
|
};
|
|
701
|
+
var installCursorUserHooks = (gateScript) => {
|
|
702
|
+
const template = readJson(join(CURSOR_PLUGIN_DIR, "hooks", "hooks.json")).hooks?.beforeShellExecution?.[0];
|
|
703
|
+
if (!template) throw new Error("bundled Cursor hooks.json missing a beforeShellExecution entry");
|
|
704
|
+
const entry = { ...template, command: `node "${gateScript}"` };
|
|
705
|
+
let userHooks = {};
|
|
706
|
+
if (existsSync(CURSOR_USER_HOOKS)) {
|
|
707
|
+
try {
|
|
708
|
+
userHooks = JSON.parse(readFileSync(CURSOR_USER_HOOKS, "utf-8"));
|
|
709
|
+
} catch {
|
|
710
|
+
try {
|
|
711
|
+
cpSync(CURSOR_USER_HOOKS, `${CURSOR_USER_HOOKS}.bak`);
|
|
712
|
+
} catch {
|
|
713
|
+
}
|
|
714
|
+
userHooks = {};
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
const hooks = userHooks.hooks ?? {};
|
|
718
|
+
const existing = Array.isArray(hooks.beforeShellExecution) ? hooks.beforeShellExecution : [];
|
|
719
|
+
const others = existing.filter((h) => !String(h.command ?? "").includes("pushary-gate"));
|
|
720
|
+
hooks.beforeShellExecution = [...others, entry];
|
|
721
|
+
writeJson(CURSOR_USER_HOOKS, { ...userHooks, version: userHooks.version ?? 1, hooks });
|
|
722
|
+
};
|
|
700
723
|
var setupCursor = async (apiKey) => {
|
|
701
724
|
console.log(`
|
|
702
725
|
${bold2("Setting up Cursor")}
|
|
@@ -720,10 +743,13 @@ var setupCursor = async (apiKey) => {
|
|
|
720
743
|
writeJson(mcpPath, mcp);
|
|
721
744
|
}
|
|
722
745
|
});
|
|
746
|
+
await spinner("Registering permission gate (~/.cursor/hooks.json)", async () => {
|
|
747
|
+
installCursorUserHooks(join(CURSOR_PLUGIN_DIR, "scripts", "pushary-gate.mjs"));
|
|
748
|
+
});
|
|
723
749
|
console.log();
|
|
724
750
|
console.log(` ${dim2("What this configured:")}`);
|
|
725
|
-
console.log(` ${dim2("\u2022")} Plugin installed to ~/.cursor/plugins/local/pushary`);
|
|
726
|
-
console.log(` ${dim2("\u2022")}
|
|
751
|
+
console.log(` ${dim2("\u2022")} Plugin installed to ~/.cursor/plugins/local/pushary (MCP tools, rule, skill)`);
|
|
752
|
+
console.log(` ${dim2("\u2022")} Permission gate registered in ~/.cursor/hooks.json \u2014 where Cursor reads hooks`);
|
|
727
753
|
console.log(` ${dim2("\u2022")} Risky shell commands route to push approval before they run`);
|
|
728
754
|
console.log(` ${dim2("\u2022")} Restart Cursor (or run Developer: Reload Window) to load it`);
|
|
729
755
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pushary/agent-hooks",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
|
|
5
5
|
"author": "Pushary <business@pushary.com>",
|
|
6
6
|
"homepage": "https://pushary.com",
|