@hasna/hooks 0.0.7 → 0.1.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.
Files changed (48) hide show
  1. package/bin/index.js +240 -42
  2. package/dist/index.js +228 -30
  3. package/hooks/hook-autoformat/README.md +39 -0
  4. package/hooks/hook-autoformat/package.json +58 -0
  5. package/hooks/hook-autoformat/src/hook.ts +223 -0
  6. package/hooks/hook-autostage/README.md +70 -0
  7. package/hooks/hook-autostage/package.json +12 -0
  8. package/hooks/hook-autostage/src/hook.ts +167 -0
  9. package/hooks/hook-commandlog/README.md +45 -0
  10. package/hooks/hook-commandlog/package.json +12 -0
  11. package/hooks/hook-commandlog/src/hook.ts +92 -0
  12. package/hooks/hook-costwatch/README.md +61 -0
  13. package/hooks/hook-costwatch/package.json +12 -0
  14. package/hooks/hook-costwatch/src/hook.ts +178 -0
  15. package/hooks/hook-desktopnotify/README.md +50 -0
  16. package/hooks/hook-desktopnotify/package.json +57 -0
  17. package/hooks/hook-desktopnotify/src/hook.ts +112 -0
  18. package/hooks/hook-envsetup/README.md +40 -0
  19. package/hooks/hook-envsetup/package.json +58 -0
  20. package/hooks/hook-envsetup/src/hook.ts +197 -0
  21. package/hooks/hook-errornotify/README.md +66 -0
  22. package/hooks/hook-errornotify/package.json +12 -0
  23. package/hooks/hook-errornotify/src/hook.ts +197 -0
  24. package/hooks/hook-permissionguard/README.md +48 -0
  25. package/hooks/hook-permissionguard/package.json +58 -0
  26. package/hooks/hook-permissionguard/src/hook.ts +268 -0
  27. package/hooks/hook-promptguard/README.md +64 -0
  28. package/hooks/hook-promptguard/package.json +12 -0
  29. package/hooks/hook-promptguard/src/hook.ts +200 -0
  30. package/hooks/hook-protectfiles/README.md +62 -0
  31. package/hooks/hook-protectfiles/package.json +58 -0
  32. package/hooks/hook-protectfiles/src/hook.ts +267 -0
  33. package/hooks/hook-sessionlog/README.md +48 -0
  34. package/hooks/hook-sessionlog/package.json +12 -0
  35. package/hooks/hook-sessionlog/src/hook.ts +100 -0
  36. package/hooks/hook-slacknotify/README.md +62 -0
  37. package/hooks/hook-slacknotify/package.json +12 -0
  38. package/hooks/hook-slacknotify/src/hook.ts +146 -0
  39. package/hooks/hook-soundnotify/README.md +63 -0
  40. package/hooks/hook-soundnotify/package.json +12 -0
  41. package/hooks/hook-soundnotify/src/hook.ts +173 -0
  42. package/hooks/hook-taskgate/README.md +62 -0
  43. package/hooks/hook-taskgate/package.json +12 -0
  44. package/hooks/hook-taskgate/src/hook.ts +169 -0
  45. package/hooks/hook-tddguard/README.md +50 -0
  46. package/hooks/hook-tddguard/package.json +12 -0
  47. package/hooks/hook-tddguard/src/hook.ts +263 -0
  48. package/package.json +3 -3
package/bin/index.js CHANGED
@@ -1886,7 +1886,12 @@ var init_registry = __esm(() => {
1886
1886
  "Code Quality",
1887
1887
  "Security",
1888
1888
  "Notifications",
1889
- "Context Management"
1889
+ "Context Management",
1890
+ "Workflow Automation",
1891
+ "Environment",
1892
+ "Permissions",
1893
+ "Observability",
1894
+ "Agent Teams"
1890
1895
  ];
1891
1896
  HOOKS = [
1892
1897
  {
@@ -2038,6 +2043,156 @@ var init_registry = __esm(() => {
2038
2043
  event: "Notification",
2039
2044
  matcher: "",
2040
2045
  tags: ["context", "compaction", "state", "backup"]
2046
+ },
2047
+ {
2048
+ name: "autoformat",
2049
+ displayName: "Auto Format",
2050
+ description: "Runs project formatter (Prettier, Biome, Ruff, Black, gofmt) after file edits",
2051
+ version: "0.1.0",
2052
+ category: "Workflow Automation",
2053
+ event: "PostToolUse",
2054
+ matcher: "Edit|Write",
2055
+ tags: ["format", "prettier", "biome", "ruff", "black", "gofmt", "style"]
2056
+ },
2057
+ {
2058
+ name: "autostage",
2059
+ displayName: "Auto Stage",
2060
+ description: "Automatically git-stages files after Claude edits them",
2061
+ version: "0.1.0",
2062
+ category: "Workflow Automation",
2063
+ event: "PostToolUse",
2064
+ matcher: "Edit|Write",
2065
+ tags: ["git", "stage", "add", "auto"]
2066
+ },
2067
+ {
2068
+ name: "tddguard",
2069
+ displayName: "TDD Guard",
2070
+ description: "Blocks implementation edits unless corresponding test files exist",
2071
+ version: "0.1.0",
2072
+ category: "Workflow Automation",
2073
+ event: "PreToolUse",
2074
+ matcher: "Edit|Write",
2075
+ tags: ["tdd", "tests", "red-green-refactor", "enforcement"]
2076
+ },
2077
+ {
2078
+ name: "envsetup",
2079
+ displayName: "Env Setup",
2080
+ description: "Warns when nvm, virtualenv, asdf, or rbenv may need activation before commands",
2081
+ version: "0.1.0",
2082
+ category: "Environment",
2083
+ event: "PreToolUse",
2084
+ matcher: "Bash",
2085
+ tags: ["nvm", "virtualenv", "asdf", "rbenv", "environment", "python", "node"]
2086
+ },
2087
+ {
2088
+ name: "permissionguard",
2089
+ displayName: "Permission Guard",
2090
+ description: "Auto-approves safe read-only commands and blocks dangerous operations",
2091
+ version: "0.1.0",
2092
+ category: "Permissions",
2093
+ event: "PreToolUse",
2094
+ matcher: "Bash",
2095
+ tags: ["permission", "allowlist", "blocklist", "safety", "auto-approve"]
2096
+ },
2097
+ {
2098
+ name: "protectfiles",
2099
+ displayName: "Protect Files",
2100
+ description: "Blocks access to .env, secrets, SSH keys, and lock files",
2101
+ version: "0.1.0",
2102
+ category: "Permissions",
2103
+ event: "PreToolUse",
2104
+ matcher: "Edit|Write|Read|Bash",
2105
+ tags: ["security", "env", "secrets", "keys", "lock-files", "protect"]
2106
+ },
2107
+ {
2108
+ name: "promptguard",
2109
+ displayName: "Prompt Guard",
2110
+ description: "Blocks prompt injection attempts and credential access requests",
2111
+ version: "0.1.0",
2112
+ category: "Permissions",
2113
+ event: "PreToolUse",
2114
+ matcher: "",
2115
+ tags: ["prompt", "injection", "security", "validation", "guard"]
2116
+ },
2117
+ {
2118
+ name: "desktopnotify",
2119
+ displayName: "Desktop Notify",
2120
+ description: "Sends native desktop notifications via osascript (macOS) or notify-send (Linux)",
2121
+ version: "0.1.0",
2122
+ category: "Notifications",
2123
+ event: "Stop",
2124
+ matcher: "",
2125
+ tags: ["notification", "desktop", "macos", "linux", "native"]
2126
+ },
2127
+ {
2128
+ name: "slacknotify",
2129
+ displayName: "Slack Notify",
2130
+ description: "Sends Slack webhook notifications when Claude finishes",
2131
+ version: "0.1.0",
2132
+ category: "Notifications",
2133
+ event: "Stop",
2134
+ matcher: "",
2135
+ tags: ["notification", "slack", "webhook", "team"]
2136
+ },
2137
+ {
2138
+ name: "soundnotify",
2139
+ displayName: "Sound Notify",
2140
+ description: "Plays a system sound when Claude finishes (macOS/Linux)",
2141
+ version: "0.1.0",
2142
+ category: "Notifications",
2143
+ event: "Stop",
2144
+ matcher: "",
2145
+ tags: ["notification", "sound", "audio", "alert"]
2146
+ },
2147
+ {
2148
+ name: "sessionlog",
2149
+ displayName: "Session Log",
2150
+ description: "Logs every tool call to .claude/session-log-<date>.jsonl",
2151
+ version: "0.1.0",
2152
+ category: "Observability",
2153
+ event: "PostToolUse",
2154
+ matcher: "",
2155
+ tags: ["logging", "audit", "session", "history", "jsonl"]
2156
+ },
2157
+ {
2158
+ name: "commandlog",
2159
+ displayName: "Command Log",
2160
+ description: "Logs every bash command Claude runs to .claude/commands.log",
2161
+ version: "0.1.0",
2162
+ category: "Observability",
2163
+ event: "PostToolUse",
2164
+ matcher: "Bash",
2165
+ tags: ["logging", "bash", "commands", "audit"]
2166
+ },
2167
+ {
2168
+ name: "costwatch",
2169
+ displayName: "Cost Watch",
2170
+ description: "Estimates session token usage and warns when budget threshold is exceeded",
2171
+ version: "0.1.0",
2172
+ category: "Observability",
2173
+ event: "Stop",
2174
+ matcher: "",
2175
+ tags: ["cost", "tokens", "budget", "usage", "monitoring"]
2176
+ },
2177
+ {
2178
+ name: "errornotify",
2179
+ displayName: "Error Notify",
2180
+ description: "Detects tool failures and logs errors to .claude/errors.log",
2181
+ version: "0.1.0",
2182
+ category: "Observability",
2183
+ event: "PostToolUse",
2184
+ matcher: "",
2185
+ tags: ["errors", "failures", "logging", "debugging"]
2186
+ },
2187
+ {
2188
+ name: "taskgate",
2189
+ displayName: "Task Gate",
2190
+ description: "Validates task completion criteria before allowing tasks to be marked done",
2191
+ version: "0.1.0",
2192
+ category: "Agent Teams",
2193
+ event: "PostToolUse",
2194
+ matcher: "",
2195
+ tags: ["tasks", "completion", "gate", "quality", "agent-teams"]
2041
2196
  }
2042
2197
  ];
2043
2198
  });
@@ -3687,11 +3842,17 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3687
3842
  import { join, dirname } from "path";
3688
3843
  import { homedir } from "os";
3689
3844
  import { fileURLToPath } from "url";
3690
- function getSettingsPath(scope = "global") {
3845
+ function getTargetSettingsDir(target) {
3846
+ if (target === "gemini")
3847
+ return ".gemini";
3848
+ return ".claude";
3849
+ }
3850
+ function getSettingsPath(scope = "global", target = "claude") {
3851
+ const dir = getTargetSettingsDir(target);
3691
3852
  if (scope === "project") {
3692
- return join(process.cwd(), ".claude", "settings.json");
3853
+ return join(process.cwd(), dir, "settings.json");
3693
3854
  }
3694
- return join(homedir(), ".claude", "settings.json");
3855
+ return join(homedir(), dir, "settings.json");
3695
3856
  }
3696
3857
  function getHookPath(name) {
3697
3858
  const hookName = name.startsWith("hook-") ? name : `hook-${name}`;
@@ -3700,8 +3861,8 @@ function getHookPath(name) {
3700
3861
  function hookExists(name) {
3701
3862
  return existsSync(getHookPath(name));
3702
3863
  }
3703
- function readSettings(scope = "global") {
3704
- const path = getSettingsPath(scope);
3864
+ function readSettings(scope = "global", target = "claude") {
3865
+ const path = getSettingsPath(scope, target);
3705
3866
  try {
3706
3867
  if (existsSync(path)) {
3707
3868
  return JSON.parse(readFileSync(path, "utf-8"));
@@ -3709,8 +3870,8 @@ function readSettings(scope = "global") {
3709
3870
  } catch {}
3710
3871
  return {};
3711
3872
  }
3712
- function writeSettings(settings, scope = "global") {
3713
- const path = getSettingsPath(scope);
3873
+ function writeSettings(settings, scope = "global", target = "claude") {
3874
+ const path = getSettingsPath(scope, target);
3714
3875
  const dir = dirname(path);
3715
3876
  if (!existsSync(dir)) {
3716
3877
  mkdirSync(dir, { recursive: true });
@@ -3718,36 +3879,48 @@ function writeSettings(settings, scope = "global") {
3718
3879
  writeFileSync(path, JSON.stringify(settings, null, 2) + `
3719
3880
  `);
3720
3881
  }
3721
- function installHook(name, options = {}) {
3722
- const { scope = "global", overwrite = false } = options;
3882
+ function getTargetEventName(internalEvent, target) {
3883
+ return EVENT_MAP[target]?.[internalEvent] || internalEvent;
3884
+ }
3885
+ function installForTarget(name, scope, overwrite, target) {
3723
3886
  const hookName = name.startsWith("hook-") ? name : `hook-${name}`;
3724
3887
  const shortName = hookName.replace("hook-", "");
3725
3888
  if (!hookExists(shortName)) {
3726
- return { hook: shortName, success: false, error: `Hook '${shortName}' not found` };
3889
+ return { hook: shortName, success: false, error: `Hook '${shortName}' not found`, target };
3727
3890
  }
3728
- const registered = getRegisteredHooks(scope);
3891
+ const registered = getRegisteredHooksForTarget(scope, target);
3729
3892
  if (registered.includes(shortName) && !overwrite) {
3730
- return { hook: shortName, success: false, error: "Already installed. Use --overwrite to replace.", scope };
3893
+ return { hook: shortName, success: false, error: "Already installed. Use --overwrite to replace.", scope, target };
3731
3894
  }
3732
3895
  try {
3733
- registerHook(shortName, scope);
3734
- return { hook: shortName, success: true, scope };
3896
+ registerHook(shortName, scope, target);
3897
+ return { hook: shortName, success: true, scope, target };
3735
3898
  } catch (error) {
3736
3899
  return {
3737
3900
  hook: shortName,
3738
3901
  success: false,
3739
- error: error instanceof Error ? error.message : "Unknown error"
3902
+ error: error instanceof Error ? error.message : "Unknown error",
3903
+ target
3740
3904
  };
3741
3905
  }
3742
3906
  }
3743
- function registerHook(name, scope = "global") {
3907
+ function installHook(name, options = {}) {
3908
+ const { scope = "global", overwrite = false, target = "claude" } = options;
3909
+ if (target === "all") {
3910
+ const claudeResult = installForTarget(name, scope, overwrite, "claude");
3911
+ installForTarget(name, scope, overwrite, "gemini");
3912
+ return { ...claudeResult, target: "all" };
3913
+ }
3914
+ return installForTarget(name, scope, overwrite, target);
3915
+ }
3916
+ function registerHook(name, scope = "global", target = "claude") {
3744
3917
  const meta = getHook(name);
3745
3918
  if (!meta)
3746
3919
  return;
3747
- const settings = readSettings(scope);
3920
+ const settings = readSettings(scope, target);
3748
3921
  if (!settings.hooks)
3749
3922
  settings.hooks = {};
3750
- const eventKey = meta.event;
3923
+ const eventKey = getTargetEventName(meta.event, target);
3751
3924
  if (!settings.hooks[eventKey])
3752
3925
  settings.hooks[eventKey] = [];
3753
3926
  const hookCommand = `hooks run ${name}`;
@@ -3759,16 +3932,16 @@ function registerHook(name, scope = "global") {
3759
3932
  entry.matcher = meta.matcher;
3760
3933
  }
3761
3934
  settings.hooks[eventKey].push(entry);
3762
- writeSettings(settings, scope);
3935
+ writeSettings(settings, scope, target);
3763
3936
  }
3764
- function unregisterHook(name, scope = "global") {
3937
+ function unregisterHook(name, scope = "global", target = "claude") {
3765
3938
  const meta = getHook(name);
3766
3939
  if (!meta)
3767
3940
  return;
3768
- const settings = readSettings(scope);
3941
+ const settings = readSettings(scope, target);
3769
3942
  if (!settings.hooks)
3770
3943
  return;
3771
- const eventKey = meta.event;
3944
+ const eventKey = getTargetEventName(meta.event, target);
3772
3945
  if (!settings.hooks[eventKey])
3773
3946
  return;
3774
3947
  const hookCommand = `hooks run ${name}`;
@@ -3779,10 +3952,10 @@ function unregisterHook(name, scope = "global") {
3779
3952
  if (Object.keys(settings.hooks).length === 0) {
3780
3953
  delete settings.hooks;
3781
3954
  }
3782
- writeSettings(settings, scope);
3955
+ writeSettings(settings, scope, target);
3783
3956
  }
3784
- function getRegisteredHooks(scope = "global") {
3785
- const settings = readSettings(scope);
3957
+ function getRegisteredHooksForTarget(scope = "global", target = "claude") {
3958
+ const settings = readSettings(scope, target);
3786
3959
  if (!settings.hooks)
3787
3960
  return [];
3788
3961
  const registered = [];
@@ -3800,24 +3973,49 @@ function getRegisteredHooks(scope = "global") {
3800
3973
  }
3801
3974
  return [...new Set(registered)];
3802
3975
  }
3976
+ function getRegisteredHooks(scope = "global") {
3977
+ return getRegisteredHooksForTarget(scope, "claude");
3978
+ }
3803
3979
  function getInstalledHooks(scope = "global") {
3804
3980
  return getRegisteredHooks(scope);
3805
3981
  }
3806
- function removeHook(name, scope = "global") {
3982
+ function removeHook(name, scope = "global", target = "claude") {
3807
3983
  const hookName = name.startsWith("hook-") ? name : `hook-${name}`;
3808
3984
  const shortName = hookName.replace("hook-", "");
3809
- const registered = getRegisteredHooks(scope);
3810
- if (!registered.includes(shortName)) {
3985
+ if (target === "all") {
3986
+ const claudeRemoved = removeHookForTarget(shortName, scope, "claude");
3987
+ const geminiRemoved = removeHookForTarget(shortName, scope, "gemini");
3988
+ return claudeRemoved || geminiRemoved;
3989
+ }
3990
+ return removeHookForTarget(shortName, scope, target);
3991
+ }
3992
+ function removeHookForTarget(name, scope, target) {
3993
+ const registered = getRegisteredHooksForTarget(scope, target);
3994
+ if (!registered.includes(name)) {
3811
3995
  return false;
3812
3996
  }
3813
- unregisterHook(shortName, scope);
3997
+ unregisterHook(name, scope, target);
3814
3998
  return true;
3815
3999
  }
3816
- var __dirname2, HOOKS_DIR;
4000
+ var __dirname2, HOOKS_DIR, EVENT_MAP;
3817
4001
  var init_installer = __esm(() => {
3818
4002
  init_registry();
3819
4003
  __dirname2 = dirname(fileURLToPath(import.meta.url));
3820
4004
  HOOKS_DIR = existsSync(join(__dirname2, "..", "..", "hooks", "hook-gitguard")) ? join(__dirname2, "..", "..", "hooks") : join(__dirname2, "..", "hooks");
4005
+ EVENT_MAP = {
4006
+ claude: {
4007
+ PreToolUse: "PreToolUse",
4008
+ PostToolUse: "PostToolUse",
4009
+ Stop: "Stop",
4010
+ Notification: "Notification"
4011
+ },
4012
+ gemini: {
4013
+ PreToolUse: "BeforeTool",
4014
+ PostToolUse: "AfterTool",
4015
+ Stop: "AfterAgent",
4016
+ Notification: "Notification"
4017
+ }
4018
+ };
3821
4019
  });
3822
4020
 
3823
4021
  // src/mcp/server.ts
@@ -3840,7 +4038,7 @@ function createHooksServer() {
3840
4038
  name: "@hasna/hooks",
3841
4039
  version: "0.0.7"
3842
4040
  });
3843
- server.tool("hooks_list", "List all available Claude Code hooks, optionally filtered by category", { category: z.string().optional().describe("Filter by category name (e.g. 'Git Safety', 'Code Quality', 'Security', 'Notifications', 'Context Management')") }, async ({ category }) => {
4041
+ server.tool("hooks_list", "List all available hooks, optionally filtered by category", { category: z.string().optional().describe("Filter by category name (e.g. 'Git Safety', 'Code Quality', 'Security', 'Notifications', 'Context Management')") }, async ({ category }) => {
3844
4042
  if (category) {
3845
4043
  const cat = CATEGORIES.find((c) => c.toLowerCase() === category.toLowerCase());
3846
4044
  if (!cat) {
@@ -3867,7 +4065,7 @@ function createHooksServer() {
3867
4065
  const projectInstalled = getRegisteredHooks("project").includes(meta.name);
3868
4066
  return { content: [{ type: "text", text: JSON.stringify({ ...meta, global: globalInstalled, project: projectInstalled }) }] };
3869
4067
  });
3870
- server.tool("hooks_install", "Install one or more hooks by registering them in Claude settings. Use scope 'global' for ~/.claude/settings.json or 'project' for .claude/settings.json", {
4068
+ server.tool("hooks_install", "Install one or more hooks by registering them in agent settings", {
3871
4069
  hooks: z.array(z.string()).describe("Hook names to install"),
3872
4070
  scope: z.enum(["global", "project"]).default("global").describe("Install scope"),
3873
4071
  overwrite: z.boolean().default(false).describe("Overwrite if already installed")
@@ -3927,7 +4125,7 @@ function createHooksServer() {
3927
4125
  }]
3928
4126
  };
3929
4127
  });
3930
- server.tool("hooks_remove", "Remove (unregister) a hook from Claude settings", {
4128
+ server.tool("hooks_remove", "Remove (unregister) a hook from agent settings", {
3931
4129
  name: z.string().describe("Hook name to remove"),
3932
4130
  scope: z.enum(["global", "project"]).default("global").describe("Scope to remove from")
3933
4131
  }, async ({ name, scope }) => {
@@ -3998,7 +4196,7 @@ function createHooksServer() {
3998
4196
  content: [{
3999
4197
  type: "text",
4000
4198
  text: JSON.stringify({
4001
- overview: "Claude Code hooks are scripts that run at specific points in a Claude Code session. Install @hasna/hooks globally, then register hooks \u2014 no files are copied to your project.",
4199
+ overview: "Hooks are scripts that run at specific points in an AI coding agent session. Install @hasna/hooks globally, then register hooks \u2014 no files are copied to your project.",
4002
4200
  events: {
4003
4201
  PreToolUse: "Fires before a tool executes. Can block the operation.",
4004
4202
  PostToolUse: "Fires after a tool executes. Runs asynchronously.",
@@ -5270,11 +5468,11 @@ function resolveScope(options) {
5270
5468
  return "project";
5271
5469
  return "global";
5272
5470
  }
5273
- program2.name("hooks").description("Install Claude Code hooks for your project").version("0.0.7");
5471
+ program2.name("hooks").description("Install hooks for AI coding agents").version("0.1.1");
5274
5472
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive hook browser").action(() => {
5275
5473
  render(/* @__PURE__ */ jsxDEV8(App, {}, undefined, false, undefined, this));
5276
5474
  });
5277
- program2.command("run").argument("<hook>", "Hook to run").description("Execute a hook (called by Claude Code)").action(async (hook) => {
5475
+ program2.command("run").argument("<hook>", "Hook to run").description("Execute a hook (called by AI coding agents)").action(async (hook) => {
5278
5476
  const meta = getHook(hook);
5279
5477
  if (!meta) {
5280
5478
  console.error(JSON.stringify({ error: `Hook '${hook}' not found` }));
@@ -5357,7 +5555,7 @@ Installing hooks (${scope})...
5357
5555
  console.log(chalk2.dim(`
5358
5556
  Registered in ${settingsFile}`));
5359
5557
  });
5360
- program2.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-a, --all", "Show all available hooks", false).option("-i, --installed", "Show only installed hooks", false).option("-r, --registered", "Show hooks registered in Claude settings", false).option("-g, --global", "Check global settings", false).option("-p, --project", "Check project settings", false).option("-j, --json", "Output as JSON", false).description("List available or installed hooks").action((options) => {
5558
+ program2.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-a, --all", "Show all available hooks", false).option("-i, --installed", "Show only installed hooks", false).option("-r, --registered", "Show registered hooks", false).option("-g, --global", "Check global settings", false).option("-p, --project", "Check project settings", false).option("-j, --json", "Output as JSON", false).description("List available or installed hooks").action((options) => {
5361
5559
  const scope = resolveScope(options);
5362
5560
  if (options.registered || options.installed) {
5363
5561
  const registered = getRegisteredHooks(scope);
@@ -5667,11 +5865,11 @@ ${meta.displayName} v${meta.version}
5667
5865
  return;
5668
5866
  }
5669
5867
  const generalDocs = {
5670
- overview: "Claude Code hooks are scripts that run at specific points in a Claude Code session. Install @hasna/hooks globally, then register hooks \u2014 no files are copied to your project.",
5868
+ overview: "Hooks are scripts that run at specific points in an AI coding agent session. Install @hasna/hooks globally, then register hooks \u2014 no files are copied to your project.",
5671
5869
  events: {
5672
5870
  PreToolUse: 'Fires before a tool executes. Can block the operation by returning { "decision": "block" }.',
5673
5871
  PostToolUse: "Fires after a tool executes. Runs asynchronously, cannot block.",
5674
- Stop: "Fires when a Claude Code session ends. Useful for notifications and cleanup.",
5872
+ Stop: "Fires when a session ends. Useful for notifications and cleanup.",
5675
5873
  Notification: "Fires on notification events like context compaction."
5676
5874
  },
5677
5875
  installation: {
@@ -5693,7 +5891,7 @@ ${meta.displayName} v${meta.version}
5693
5891
  howItWorks: {
5694
5892
  install: "bun install -g @hasna/hooks",
5695
5893
  register: "hooks install gitguard \u2192 writes to ~/.claude/settings.json",
5696
- execution: "Claude Code runs 'hooks run gitguard' \u2192 executes hook from global package",
5894
+ execution: "Agent runs 'hooks run gitguard' \u2192 executes hook from global package",
5697
5895
  noFileCopy: "No files are copied to your project. Hooks run from the global @hasna/hooks package."
5698
5896
  }
5699
5897
  };
@@ -5739,7 +5937,7 @@ ${meta.displayName} v${meta.version}
5739
5937
  console.log(` hooks docs --json Machine-readable documentation`);
5740
5938
  console.log();
5741
5939
  });
5742
- program2.command("mcp").option("-s, --stdio", "Use stdio transport (for Claude Code integration)", false).option("-p, --port <port>", "Port for SSE transport", "39427").description("Start MCP server for AI agent integration").action(async (options) => {
5940
+ program2.command("mcp").option("-s, --stdio", "Use stdio transport (for agent MCP integration)", false).option("-p, --port <port>", "Port for SSE transport", "39427").description("Start MCP server for AI agent integration").action(async (options) => {
5743
5941
  if (options.stdio) {
5744
5942
  const { startStdioServer: startStdioServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
5745
5943
  await startStdioServer2();