cursor-hook
v0.2.0
Published
CLI tool to install Cursor hooks
Readme
Cursor Hook CLI
A TypeScript CLI tool to install Cursor hooks from Git repositories.
Installation
npm install -g cursor-hook
# or
npx cursor-hook install <repository>Usage
cursor-hook install <repository-or-path>Repository Formats
The tool supports multiple repository reference formats and local paths:
Git Repositories:
- GitHub owner/repo:
beautyfree/cursor-window-activate-hook - Full GitHub URL:
github.com/beautyfree/cursor-window-activate-hook - GitLab:
gitlab.com/owner/repo - Full Git URL:
https://github.com/owner/repo.gitor[email protected]:owner/repo.git
Local Paths:
- Absolute path:
/path/to/local/repo - Relative path:
./local-repoor../parent/repo
Examples
# Install from GitHub repository
npx cursor-hook install beautyfree/cursor-window-activate-hook
# Install from local directory
npx cursor-hook install ./cursor-window-activate-hook
npx cursor-hook install /Users/me/projects/my-hookConfiguration File
Repositories must include a cursor-hook.config.json file in the repository root. The CLI loads it after cloning or when using a local path.
Simple Example (single command for all platforms)
When the installation command is the same across all platforms, use a simple string:
{
"installCommand": "npm install --production --no-save --silent --no-audit --no-fund || true",
"files": {
"hooks": ["activate-window"],
"rules": []
},
"hooks": {
"beforeSubmitPrompt": [
{
"command": "node $HOME/.cursor/hooks/activate-window/activate-window.js"
}
]
}
}Platform-Specific Commands (system deps only)
For system-wide dependencies only (e.g. xdotool), use systemInstallCommand (runs once):
{
"systemInstallCommand": {
"linux": "sudo apt-get install -y xdotool || sudo yum install -y xdotool || true",
"macos": "",
"windows": "",
"default": "echo 'No installation needed for this platform'"
},
"files": { "hooks": ["file1.sh"], "rules": [] },
"hooks": { ... }
}System + per-hook (both)
When you need both system deps (run once) and per-hook build (e.g. npm i && npm run build in each hook folder), use systemInstallCommand and installCommand:
{
"systemInstallCommand": {
"linux": "sudo apt-get install -y xdotool || sudo yum install -y xdotool || true",
"macos": "",
"windows": "",
"default": "echo 'No system install needed'"
},
"installCommand": "npm i --no-save --silent && npm run build || true",
"files": {
"hooks": ["hooks/docs", "hooks/activate"],
"rules": []
},
"hooks": {
"afterFileEdit": [{ "command": "node $HOME/.cursor/hooks/docs/dist/docs.js" }],
"stop": [{ "command": "node $HOME/.cursor/hooks/activate/dist/activate.js" }]
}
}Order: 1) systemInstallCommand runs once from hooks dir. 2) installCommand runs in each hook folder (docs, activate).
Required environment variables
You can require the user to provide environment variables during install. Values are injected into the hook command (no .env file). The CLI prepends VAR=value (Unix) or set "VAR=value" && (Windows) so the hook process receives the variables.
You can set requiredEnv in two places:
- Top-level — same env vars for every hook that doesn’t define its own:
{
"requiredEnv": ["API_KEY", { "name": "SECRET", "description": "Optional hint" }],
"hooks": {
"afterFileEdit": [{ "command": "node $HOME/.cursor/hooks/docs/docs.js" }]
}
}- Per-hook — each hook can declare its own env vars (overrides top-level for that hook):
{
"hooks": {
"afterFileEdit": [
{ "command": "node $HOME/.cursor/hooks/docs/docs.js", "requiredEnv": ["API_KEY"] }
],
"beforeSubmitPrompt": [
{ "command": "node $HOME/.cursor/hooks/activate/activate.js", "requiredEnv": ["SECRET_TOKEN", "API_URL"] }
]
}
}- User is prompted once per unique variable name; current
process.envis used as default. Only the vars required by that hook are injected into each command (e.g. thebeforeSubmitPromptcommand above gets onlySECRET_TOKENandAPI_URL).
Configuration Fields
- systemInstallCommand (optional): Run once from the hooks directory (e.g. apt-get, brew). String or platform object. Runs before
installCommand. - installCommand (optional): Run in each hook folder (e.g. npm i && npm run build). String or platform object. For system deps run once, use systemInstallCommand.
- requiredEnv (optional): Top-level list of env var names (or
{ "name", "description?" }) to prompt for; applied to all hooks that don’t set their own requiredEnv. Values are injected into the hook command inhooks.json. - files (optional): Object with:
- hooks: Array of paths (files or directories) to copy into
.cursor/hooks - rules: Array of paths (files or directories) to copy into
.cursor/rules(Cursor Rules for AI)
- hooks: Array of paths (files or directories) to copy into
- hooks (required): Object mapping hook names to arrays of hook configurations. Each entry must have a command (string) and may have requiredEnv (array, same format as top-level) for that hook only. Example:
"afterFileEdit": [{ "command": "node $HOME/.cursor/hooks/docs/dist/docs.js", "requiredEnv": ["API_KEY"] }]
Path behavior: Paths in files.hooks and files.rules are relative to the repository root. Each item is copied into the target dir using its last path segment (e.g. hooks/docs → .../.cursor/hooks/docs). If a target path already exists, the CLI will prompt before overwriting.
Install command cwd: installCommand runs with the current working directory set to each hook folder (or to the hooks dir if there are no hook folders). Do not put cd <path> in the command—use only the build steps (e.g. npm i && npm run build || true).
Installation Flow
- Downloads the repository to a temporary directory (or uses local path if provided)
- Loads
cursor-hook.config.jsonfrom the repository root - Prompts user to choose installation location:
- Global:
~/.cursor/hooks.json(applies to all projects) - Project:
.cursor/hooks.json(applies to current project only)
- Global:
- If any hook has requiredEnv (per-hook or top-level), prompts for each variable once and injects only the vars each hook needs into its command in
hooks.json. - Downloads files:
files.hooks→.cursor/hooks,files.rules→.cursor/rules(if present) - Executes commands: systemInstallCommand once (if set), then installCommand in each hook folder (or once from hooks dir if no hook folders)
- Creates backup of existing
hooks.json(if present) - Merges hooks configuration into
hooks.json(preserves existing hooks, prevents duplicates)
Cross-Platform Support
The tool works on:
- macOS
- Linux
- Windows (PowerShell, CMD, Git Bash)
Path variables like $HOME are automatically expanded on all platforms.
Types for hook authors
If you are implementing a hook script (e.g. in Node.js) and want typed payloads, install the package and import types:
npm install cursor-hookimport type { AfterFileEditPayload, HookEventName } from 'cursor-hook';See Cursor Hooks documentation for payload and response schemas. The package re-exports TypeScript types that match those schemas.
Examples
Example Repository
See cursor-window-activate-hook for a complete example of a hook repository with:
cursor-hook.config.jsonconfiguration file- Platform-specific install commands
- Hook scripts and configuration
This repository demonstrates:
- How to structure a hook package
- Platform-specific dependency installation
- Proper hook configuration
Notes
- Backup: Before merging, the CLI creates
hooks.json.backupifhooks.jsonexists. To restore: copy the backup overhooks.json. - Overwrite: If target paths (e.g.
.../hooks/docs) already exist, the CLI asks for confirmation before overwriting.
Development
# Install dependencies
npm install
# Build
npm run build
# Run in development mode
npm run dev install <repository>License
MIT
