### Example Installation Output Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md This output shows the typical progress and prompts during a cursor-hook installation process. ```text 🚀 Installing Cursor hooks from: beautyfree/cursor-window-activate-hook đŸ“Ĩ Downloading repository... ✓ Repository downloaded 📋 Loading configuration... ✓ Configuration loaded Where would you like to install the hooks? ❯ Project (.cursor/hooks.json) - applies to current project only Global (~/.cursor/hooks.json) - applies to all projects 🔐 Required environment variables: API_KEY: [default: ] SECRET: Optional hint [user enters values] âš ī¸ The following paths already exist and would be overwritten: ~/.cursor/hooks/my-hook Overwrite these paths? (backup or rename them first if you need to keep current content) 📁 Downloading hooks... ✓ Hooks downloaded to: ~/.cursor/hooks âš™ī¸ Installing system dependencies... ✓ System dependencies installed âš™ī¸ Installing dependencies in my-hook... ✓ Dependencies installed 💾 Backup created: ~/.cursor/hooks.json.backup 🔗 Merging hooks configuration... âš ī¸ Skipped 1 hook(s) that already exist: - beforeSubmitPrompt: node $HOME/.cursor/hooks/my-hook/hook.js â„šī¸ All hooks already exist, no changes made ✓ Hooks configuration updated: ~/.cursor/hooks.json ✅ Installation complete! 📌 Important: Restart Cursor for hooks to take effect ``` -------------------------------- ### Example: Install from Local Directory Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Demonstrates installing a Cursor hook from a local directory using the `npx cursor-hook install` command. ```bash npx cursor-hook install ./cursor-window-activate-hook npx cursor-hook install /Users/me/projects/my-hook ``` -------------------------------- ### Example CLI Usage: Install Command Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Demonstrates the basic usage of the `cursor-hook install` command to install hooks from a repository. ```bash cursor-hook install ``` -------------------------------- ### Install Flow Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/architecture.md Illustrates the step-by-step process from user command to successful hook installation, detailing interactions between different modules. ```markdown User runs: cursor-hook install ↓ Parse CLI args (index.ts) ↓ installHooks() called (install.ts) ↓ Detect source (git/downloader.ts) - Check if local path exists - If not, parse as Git URL and clone ↓ Load config (git/downloader.ts) - Read cursor-hook.config.json - Parse JSON ↓ Validate config (config/schema.ts) - Check all required fields - Validate types ↓ Prompt for location (utils/prompts.ts) - User chooses global or project ↓ Collect env vars (utils/prompts.ts) - Determine which vars each hook needs - Prompt user for each unique var ↓ Check existing paths (files/downloader.ts) - Find what would be overwritten ↓ Ask for confirmation (utils/prompts.ts) - If paths exist, prompt user ↓ Download files (files/downloader.ts) - Copy files.hooks to .cursor/hooks - Copy files.rules to .cursor/rules ↓ Run system install (shell/executor.ts) - Execute systemInstallCommand once - Select platform-specific variant ↓ Run per-hook install (shell/executor.ts) - Execute installCommand in each hook dir ↓ Read existing hooks.json (hooks/manager.ts) - Create default if doesn't exist ↓ Merge hooks (hooks/manager.ts) - Add new hooks, skip duplicates - Expand paths ($HOME → absolute) ↓ Inject env vars (hooks/manager.ts) - Prefix each command with its env vars ↓ Write hooks.json (hooks/manager.ts) - Format with 2-space indentation - Create .cursor directory if needed ↓ Cleanup (git/downloader.ts) - Delete temp directory if cloned ↓ Success message ``` -------------------------------- ### Install Command - String Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Specify a single command string for per-hook installations, such as building dependencies. This command runs after the system install command. ```json { "installCommand": "npm install --production && npm run build" } ``` -------------------------------- ### System Install Command - Platform-Specific Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Define platform-specific commands for system-wide dependency installation. A default command is used if no specific platform command matches. ```json { "systemInstallCommand": { "linux": "sudo apt-get install -y xdotool || true", "macos": "brew install xdotool || true", "windows": "choco install xdotool -y || exit /b 0", "default": "echo 'Manual install required' || true" } } ``` -------------------------------- ### Example CLI Usage: Install with Specific Repository Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Shows how to install hooks from a specific Git repository URL using the `cursor-hook install` command. ```bash cursor-hook install git+https://github.com/example/my-hooks.git ``` -------------------------------- ### Install Command - Platform-Specific Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Configure platform-specific commands for per-hook installations. This allows tailoring build steps for different operating systems. ```json { "installCommand": { "linux": "npm ci && npm run build", "macos": "npm ci && npm run build", "windows": "npm ci && npm run build", "default": "npm i && npm run build" } } ``` -------------------------------- ### Example Platform-Specific Configuration Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Demonstrates how to define platform-specific installation commands within the cursor-hook configuration. ```json { "installCommand": { "linux": "npm install -g cursor-hook-linux", "macos": "npm install -g cursor-hook-macos", "windows": "npm install -g cursor-hook-windows", "default": "npm install -g cursor-hook" } } ``` -------------------------------- ### Install Command - Per-Hook Execution Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Demonstrates how the installCommand is executed in separate hook directories when multiple hooks are specified in the files.hooks configuration. ```json { "files": { "hooks": ["hooks/formatter", "hooks/linter"] }, "installCommand": "npm install --production && npm run build" } ``` -------------------------------- ### System Install Command - String Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Configure system-wide dependencies using a single command string that applies to all platforms. This command runs once before the per-hook install command. ```json { "systemInstallCommand": "sudo apt-get install -y xdotool || true" } ``` -------------------------------- ### Cursor Hook Configuration: Simple Install Command Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md A simple `cursor-hook.config.json` example where the installation command is the same across all platforms. This configuration defines the install command and specifies hook files. ```json { "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" } ] } } ``` -------------------------------- ### Command Variable Expansion Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Illustrates the expansion of the `$HOME` variable in a command string. This variable is expanded during installation. ```json { "command": "node $HOME/.cursor/hooks/my-hook/index.js" } ``` -------------------------------- ### cursor-hook.config.json Example for Hook Distribution Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/INDEX.md Configure installation procedures for distributing hooks via cursor-hook. This example defines a post-install command, specifies files to download, and registers a hook for 'beforeShellExecution'. ```json { "installCommand": "npm install --production", "files": { "hooks": ["dist"] }, "hooks": { "beforeShellExecution": [ { "command": "node $HOME/.cursor/hooks/dist/hook.js" } ] } } ``` -------------------------------- ### Cursor Hook Configuration: Platform-Specific System Install Command Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Configuration for system-wide dependencies using `systemInstallCommand`. This example specifies different installation commands for Linux, macOS, and Windows, with a default fallback. ```json { "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": { ... } } ``` -------------------------------- ### Install Hooks from Full GitHub URL Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks by providing the full GitHub repository URL. ```bash # github.com domain cursor-hook install github.com/beautyfree/cursor-window-activate-hook ``` -------------------------------- ### Example Cursor Hook Configuration (JSON) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md A sample configuration file for cursor-hook, demonstrating settings for installation commands and hook definitions. ```json { "systemInstallCommand": "npm install -g cursor-hook", "installCommand": "cursor-hook install", "requiredEnv": [ "MY_API_KEY" ], "files": { "hooks": [ "./hooks/**/*.js" ], "rules": [ "./rules/**/*.js" ] }, "hooks": { "preToolUse": { "priority": 100, "enabled": true }, "afterAgentResponse": { "priority": 50, "enabled": false } } } ``` -------------------------------- ### Install Hooks from GitHub Shorthand Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks using the 'owner/repo' format for GitHub repositories. ```bash # owner/repo format cursor-hook install beautyfree/cursor-window-activate-hook ``` -------------------------------- ### Example Hook Implementation Pattern Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Illustrates a common pattern for implementing hooks, including type definitions and handler setup. ```typescript import { HookEventName, HookPayloadMap, HookResponseMap, HookHandler, } from "@cursorless/common"; type MyEvent = HookEventName.preToolUse; type MyPayload = HookPayloadMap[MyEvent]; type MyResponse = HookResponseMap[MyEvent]; const handler: HookHandler = async (payload: MyPayload): Promise => { // Your hook logic here console.log("Received tool use payload:", payload); return { success: true }; }; export default handler; ``` -------------------------------- ### Cursor Hook Configuration: System and Per-Hook Installation Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Configuration that includes both system-wide dependencies (`systemInstallCommand`) and per-hook build steps (`installCommand`). The order of execution is system install first, then per-hook installs. ```json { "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" }] } } ``` -------------------------------- ### Install Hooks from Full Git URL (HTTP) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks using a full Git URL with HTTP protocol. ```bash # HTTP cursor-hook install http://git.example.com/repo.git ``` -------------------------------- ### Install Hooks from GitLab URL Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks using a GitLab repository URL. ```bash cursor-hook install gitlab.com/owner/repo ``` -------------------------------- ### Install Cursor Hook using npx Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Install and run the CLI tool for a specific repository using npx. This is useful for one-off installations or testing. ```bash npx cursor-hook install ``` -------------------------------- ### Test with `npx` and Local Path Source: https://github.com/beautyfree/cursor-hook/blob/main/DEVELOPMENT.md Test the CLI as if it were published by packing it into a .tgz file and installing it globally. ```bash cd cursor-hook-cli npm pack # Creates a .tgz file npm install -g ./cursor-hook-0.1.0.tgz cursor-hook install ../cursor-window-activate-hook ``` -------------------------------- ### Install CLI Globally or via npx Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Instructions for installing the cursor-hook CLI globally using npm or executing it directly with npx. ```bash npm install -g cursor-hook # or npx cursor-hook install ``` -------------------------------- ### Install Hooks from Local Relative Path Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks from a local directory using a relative path. ```bash # Relative path cursor-hook install ./my-hook cursor-hook install ../parent/my-hook ``` -------------------------------- ### Install a Cursor Hook Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/INDEX.md Use this command to install a hook from a specified repository URL. Follow the CLI prompts for configuration. ```bash npx cursor-hook install beautyfree/cursor-window-activate-hook ``` -------------------------------- ### Install Cursor Hook CLI Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Use the `cursor-hook install` command to install hooks from a specified repository or local path. The tool handles various repository reference formats. ```bash cursor-hook install ``` -------------------------------- ### Install Hooks from Local Absolute Path Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks from a local directory using an absolute path. ```bash # Absolute path cursor-hook install /Users/me/projects/my-hook ``` -------------------------------- ### Install Hooks from Full Git URL (SSH) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks using a full Git URL with SSH protocol. ```bash # SSH cursor-hook install git@github.com:owner/repo.git ``` -------------------------------- ### Install Hooks from Full Git URL (HTTPS) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Install hooks using a full Git URL with HTTPS protocol. ```bash # HTTPS cursor-hook install https://github.com/owner/repo.git ``` -------------------------------- ### Example hooks.json Configuration Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Illustrates the structure of a runtime `hooks.json` file, showing how to configure commands for different hook events like `beforeShellExecution` and `afterFileEdit`. ```json { "version": 1, "hooks": { "beforeShellExecution": [ { "command": "$HOME/.cursor/hooks/check-command/check.js" } ], "afterFileEdit": [ { "command": "$HOME/.cursor/hooks/auto-format/format.js", "timeout": 30 } ] } } ``` -------------------------------- ### Install Cursor Hook CLI Globally Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Install the CLI tool globally using npm. This command makes the `cursor-hook` command available system-wide. ```bash npm install -g cursor-hook ``` -------------------------------- ### Example Hook Handler Implementations Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Demonstrates how to implement HookHandler for 'beforeShellExecution' and 'sessionStart' events, showcasing type inference for payloads and return types. ```typescript import type { HookHandler } from 'cursor-hook' const beforeShell: HookHandler<'beforeShellExecution'> = (payload) => { // payload is BeforeShellExecutionPayload // return type must be BeforeShellExecutionResponse return { permission: 'allow' } } const sessionStart: HookHandler<'sessionStart'> = async (payload) => { // async is allowed return { continue: true, additional_context: 'Some context', } } ``` -------------------------------- ### Define Required Environment Variables (Object Format) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Specify environment variables with descriptions for clarity. Users are prompted for these during installation. ```json { "requiredEnv": [ "API_KEY", { "name": "SECRET_TOKEN", "description": "OAuth token for authentication" } ] } ``` -------------------------------- ### Install cursor-hook package Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md Use this npm command to install the cursor-hook package, which provides types for hook authors implementing scripts in Node.js. ```bash npm install cursor-hook ``` -------------------------------- ### subagentStart Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before a subagent is started, allowing for pre-execution checks. ```APIDOC ## subagentStart ### Description Fired before a subagent is started, allowing for pre-execution checks. ### Payload `SubagentStartPayload` ### Response `SubagentStartResponse` ### Response Fields - **decision** ('allow' | 'deny') - Whether to allow subagent start - **reason** (string) - Explanation for the decision ``` -------------------------------- ### Simple Command Hook Configuration Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md A basic hook configuration that installs npm dependencies and runs a validator script before submission. ```json { "installCommand": "npm install --production", "files": { "hooks": ["dist"] }, "hooks": { "beforeSubmitPrompt": [ { "command": "node $HOME/.cursor/hooks/dist/validator.js" } ] } } ``` -------------------------------- ### Example: Implementing a Specific Hook Handler Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Shows how to use the `HookHandler` type to implement a strongly typed handler for the `beforeSubmitPrompt` event. ```typescript import type { HookHandler } from 'cursor-hook' const handleBeforeSubmitPrompt: HookHandler<'beforeSubmitPrompt'> = async (payload) => { // payload is fully typed as BeforeSubmitPromptPayload const { prompt, attachments } = payload // return type is fully typed as BeforeSubmitPromptResponse return { continue: true, user_message: 'Prompt looks good', } } ``` -------------------------------- ### Example hook configuration in cursor-hook.config.json Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md This JSON snippet shows an example of a hook configuration within the cursor-hook.config.json file. It includes a hook named 'afterFileEdit' with a command to execute a Node.js script and specifies a required environment variable 'API_KEY'. ```json { "hooks": { "afterFileEdit": [ { "command": "node $HOME/.cursor/hooks/docs/dist/docs.js", "requiredEnv": ["API_KEY"] } ] } } ``` -------------------------------- ### Configuring Required Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md Example of a cursor-hook.config.json file specifying required environment variables for a hook, including descriptions for user prompts. ```json { "hooks": { "afterFileEdit": [ { "command": "node $HOME/.cursor/hooks/analyzer/index.js", "requiredEnv": ["API_KEY", { "name": "API_URL", "description": "Base API URL" }] } ] } } ``` -------------------------------- ### Example Async Hook with Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Shows an asynchronous hook implementation that utilizes environment variables. ```typescript import { HookEventName, HookPayloadMap, HookResponseMap, HookHandler, } from "@cursorless/common"; type MyEvent = HookEventName.afterAgentResponse; type MyPayload = HookPayloadMap[MyEvent]; type MyResponse = HookResponseMap[MyEvent]; const handler: HookHandler = async (payload: MyPayload): Promise => { const apiKey = process.env.MY_API_KEY; if (!apiKey) { console.warn("MY_API_KEY environment variable not set."); return { success: false, message: "API key missing" }; } // Use apiKey for external API calls console.log("Processing agent response with API Key..."); return { success: true }; }; export default handler; ``` -------------------------------- ### Display Cursor Hook Version Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Use this command to check the installed version of the cursor-hook tool. This is useful for verifying installation and compatibility. ```bash cursor-hook --version ``` -------------------------------- ### Use `npm link` for Global CLI Testing Source: https://github.com/beautyfree/cursor-hook/blob/main/DEVELOPMENT.md Create a global symlink to test the CLI as if it were installed globally. Remember to build first and unlink later. ```bash cd cursor-hook-cli npm run build npm link # Now you can use it from anywhere: cursor-hook install ../cursor-window-activate-hook cursor-hook install beautyfree/cursor-window-activate-hook # To unlink later: npm unlink -g cursor-hook ``` -------------------------------- ### Example: Handling Multiple Hook Events Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Demonstrates how to use the `isHookPayloadOf` type guard to handle different hook events like `beforeShellExecution` and `afterFileEdit`. ```typescript import { isHookPayloadOf, type HookPayload } from 'cursor-hook' export default async function handler(payload: unknown): Promise { if (isHookPayloadOf(payload, 'beforeShellExecution')) { const { command, cwd } = payload console.log(`Shell command: ${command} in ${cwd}`) return { permission: 'allow' } } if (isHookPayloadOf(payload, 'afterFileEdit')) { const { file_path, edits } = payload console.log(`File edited: ${file_path}, ${edits.length} edits`) return {} } return {} } ``` -------------------------------- ### Example Type Guard Usage Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Demonstrates how to use a type guard function to narrow down the type of a hook payload at runtime. ```typescript import { HookEventName, HookPayloadMap, isHookPayloadOf, } from "@cursorless/common"; const payload: HookPayloadMap[HookEventName.preToolUse] = { // ... payload properties }; if (isHookPayloadOf(HookEventName.preToolUse, payload)) { // payload is now known to be HookPayloadMap[HookEventName.preToolUse] console.log("This is a preToolUse payload."); } ``` -------------------------------- ### Development commands for cursor-hook Source: https://github.com/beautyfree/cursor-hook/blob/main/README.md These bash commands are used for developing the cursor-hook project. They cover installing dependencies, building the project, and running it in development mode with an install command. ```bash # Install dependencies npm install # Build npm run build # Run in development mode npm run dev install ``` -------------------------------- ### Example: Intercepting Secret Prompts Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Example handler for the beforeSubmitPrompt hook. Blocks prompts containing 'secret' and provides a user message. ```typescript import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'beforeSubmitPrompt'> = (payload) => { if (payload.prompt.includes('secret')) { return { continue: false, user_message: 'Prompts with "secret" are blocked', } } return { continue: true } } ``` -------------------------------- ### Define Required Environment Variables (String Format) Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Specify environment variables that users must provide during installation. These are injected into hook commands. ```json { "requiredEnv": ["API_KEY", "SECRET_TOKEN"] } ``` -------------------------------- ### Testing a BeforeShellExecution Hook Locally Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md This example demonstrates how to create a mock payload for the `beforeShellExecution` event and test your hook handler locally. Ensure you import the correct payload type and your handler function. ```typescript import type { BeforeShellExecutionPayload } from 'cursor-hook' import handler from './your-hook' const testPayload: BeforeShellExecutionPayload = { hook_event_name: 'beforeShellExecution', conversation_id: 'test-conv-123', generation_id: 'test-gen-456', model: 'gpt-4', cursor_version: '0.42.0', workspace_roots: ['/home/user/project'], user_email: 'user@example.com', transcript_path: '/path/to/transcript.md', command: 'npm test', cwd: '/home/user/project', timeout: 30, } const response = handler(testPayload) console.log(response) // Should be: { permission: 'allow' } ``` -------------------------------- ### TypeScript Hook Handler Example Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/INDEX.md Implement a hook script using the HookHandler type for full type safety. Use isHookPayloadOf() for runtime type narrowing. This example shows a handler for the 'beforeShellExecution' event. ```typescript import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'beforeShellExecution'> = (payload) => { // payload is fully typed as BeforeShellExecutionPayload return { permission: 'allow' } } ``` -------------------------------- ### Hook with Required Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Configures a hook that requires specific environment variables (API_KEY, API_URL) for its operation. These variables will be prompted during installation. ```json { "installCommand": "npm install --production", "requiredEnv": [ "API_KEY", { "name": "API_URL", "description": "Base URL for the API" } ], "files": { "hooks": ["dist"] }, "hooks": { "afterFileEdit": [ { "command": "node $HOME/.cursor/hooks/dist/analyzer.js" } ] } } ``` -------------------------------- ### Cursor Hook Configuration File Structure Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md This JSON object illustrates the overall structure of the cursor-hook.config.json file, showing key fields for installation commands, required environment variables, file mappings, and hook definitions. ```json { "systemInstallCommand": "apt-get install -y xdotool || true", "installCommand": "npm install --production", "requiredEnv": ["API_KEY"], "files": { "hooks": ["src/hook"], "rules": ["src/rules"] }, "hooks": { "beforeShellExecution": [ { "command": "node $HOME/.cursor/hooks/my-hook/index.js", "requiredEnv": ["API_KEY"] } ] } } ``` -------------------------------- ### Example Error Handling Pattern Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/README.md Illustrates a pattern for handling errors within a hook, returning a specific error response. ```typescript import { HookEventName, HookPayloadMap, HookResponseMap, HookHandler, } from "@cursorless/common"; type MyEvent = HookEventName.beforeShellExecution; type MyPayload = HookPayloadMap[MyEvent]; type MyResponse = HookResponseMap[MyEvent]; const handler: HookHandler = async (payload: MyPayload): Promise => { try { // Simulate an operation that might fail if (payload.command.includes("dangerous")) { throw new Error("Command is too dangerous to execute."); } console.log("Executing command:", payload.command); return { success: true }; } catch (error: any) { console.error("Error during shell execution:", error.message); return { success: false, message: error.message }; } }; export default handler; ``` -------------------------------- ### Example Duplicate Hook Prevention Message Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md This message indicates that one or more hooks were skipped because they already exist. ```bash âš ī¸ Skipped 1 hook(s) that already exist: - beforeSubmitPrompt: node $HOME/.cursor/hooks/my-hook/hook.js ``` -------------------------------- ### Platform-Specific System Dependencies Hook Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Configures platform-specific system dependencies for Linux, macOS, and Windows, along with an npm installation and a hook script. ```json { "systemInstallCommand": { "linux": "sudo apt-get install -y xdotool || true", "macos": "brew install xdotool || true", "windows": "", "default": "echo 'xdotool installation skipped'" }, "installCommand": "npm install --production", "files": { "hooks": ["hooks/activate"] }, "hooks": { "beforeSubmitPrompt": [ { "command": "node $HOME/.cursor/hooks/activate/index.js" } ] } } ``` -------------------------------- ### Example Usage of isHookPayloadOf Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Illustrates how to use the isHookPayloadOf type guard in a generic handler to check payload types for 'beforeShellExecution' and 'afterFileEdit' events. ```typescript import { isHookPayloadOf, type HookPayload } from 'cursor-hook' async function genericHandler(payload: unknown): Promise { if (!payload || typeof payload !== 'object') { return {} } if (isHookPayloadOf(payload, 'beforeShellExecution')) { // payload is now BeforeShellExecutionPayload return { permission: payload.command.includes('rm') ? 'deny' : 'allow' } } if (isHookPayloadOf(payload, 'afterFileEdit')) { // payload is now AfterFileEditPayload console.log(`File edited: ${payload.file_path}`) return {} } return {} } ``` -------------------------------- ### Display Cursor Hook Help Information Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Run this command to view all available commands, options, and usage instructions for the cursor-hook CLI. It provides a comprehensive overview of the tool's capabilities. ```bash cursor-hook --help ``` -------------------------------- ### SessionStartResponse Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Expected response from `sessionStart` hook handlers. Allows configuration of environment variables, additional context, and session continuation. ```APIDOC ### SessionStartResponse ```ts interface SessionStartResponse { env?: Record additional_context?: string continue?: boolean user_message?: string } ``` Expected response from `sessionStart` hook handlers. | Field | Type | Description | |-------|------|-------------| | env | Record | Environment variables to inject into the session context | | additional_context | string | Extra system message content to prepend to the conversation | | continue | boolean | Whether to proceed with the session (false aborts immediately) | | user_message | string | User-facing feedback message | ``` -------------------------------- ### SessionStartPayload Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Payload for the `sessionStart` hook, fired when a conversation begins. It includes session details and composer mode. ```APIDOC ### SessionStartPayload ```ts interface SessionStartPayload extends HookPayloadBase { hook_event_name: 'sessionStart' session_id: string is_background_agent: boolean composer_mode?: 'agent' | 'ask' | 'edit' } ``` Payload for the `sessionStart` hook, fired when a conversation begins. **Response type:** `SessionStartResponse` ``` -------------------------------- ### BeforeMCPExecutionPayload Type Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Defines the payload for the 'beforeMCPExecution' hook, triggered before an MCP tool starts. It includes the tool name and its input. ```typescript interface BeforeMCPExecutionPayload extends HookPayloadBase { hook_event_name: 'beforeMCPExecution' tool_name: string tool_input: unknown url?: string command?: string } ``` -------------------------------- ### Specify Files for Rules Directory Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Define paths for files or directories to be copied into the `.cursor/rules` directory. User is prompted before overwriting. ```json { "files": { "rules": ["cursor-rules.md"] } } ``` -------------------------------- ### Specify Files for Hooks Directory Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Define paths for files or directories to be copied into the `.cursor/hooks` directory. User is prompted before overwriting. ```json { "files": { "hooks": [ "src/formatter", "src/linter.js" ] } } ``` -------------------------------- ### Multiple Hook Configurations Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Define multiple hooks, each with its own commands, required environment variables, and timeouts. All defined commands will be executed. ```json { "hooks": { "sessionStart": [ { "command": "node $HOME/.cursor/hooks/setup/setup.js", "requiredEnv": ["PROJECT_ID"] } ], "beforeShellExecution": [ { "command": "node $HOME/.cursor/hooks/security/check.js" } ], "afterFileEdit": [ { "command": "node $HOME/.cursor/hooks/format/format.js", "timeout": 30 } ] } } ``` -------------------------------- ### Simple Hook Configuration Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Register a command to be executed when a specific hook event fires. Multiple commands can be registered per hook. ```json { "hooks": { "beforeShellExecution": [ { "command": "node $HOME/.cursor/hooks/check-command/check.js" } ] } } ``` -------------------------------- ### sessionStart Hook Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Details for the `sessionStart` hook, including its payload and response types. This hook is fired when a conversation session begins. ```APIDOC ## sessionStart Hook ### Description Fired when a conversation session begins. ### Method Hook Event ### Endpoint N/A (Internal hook event) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body **sessionStartPayload** - **hook_event_name** (string) - Required - Must be 'sessionStart' - **session_id** (string) - Required - The unique identifier for the session - **is_background_agent** (boolean) - Required - Indicates if the session is running in the background - **composer_mode** (string) - Optional - The mode of the composer ('agent', 'ask', or 'edit') ### Request Example ```json { "hook_event_name": "sessionStart", "session_id": "sess_12345", "is_background_agent": false, "composer_mode": "ask" } ``` ### Response #### Success Response **sessionStartResponse** - **env** (Record) - Optional - Environment variables to inject into the session - **additional_context** (string) - Optional - Extra context to prepend to the conversation - **continue** (boolean) - Optional - Whether to continue the session (false aborts) - **user_message** (string) - Optional - Message to display to the user #### Response Example ```json { "env": { "API_KEY": "abcdef123" }, "additional_context": "Please review the following code.", "continue": true, "user_message": "Session started successfully." } ``` ``` -------------------------------- ### Run `npm run dev` for Local Development Source: https://github.com/beautyfree/cursor-hook/blob/main/DEVELOPMENT.md Use this command to run TypeScript directly without building. It's recommended for development. ```bash cd cursor-hook-cli npm run dev install ../cursor-window-activate-hook ``` -------------------------------- ### Handle Matched Tools in Hook Script Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md In the hook script, access payload properties like `tool_name` which will be pre-filtered by the `matcher` in the configuration. This example logs the bash command being checked. ```typescript import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'preToolUse'> = (payload) => { // payload.tool_name will be 'bash' (due to matcher) console.log(`Checking bash command: ${payload.tool_input}`) return { decision: 'allow' } } ``` -------------------------------- ### Process Files Within Specific Workspaces Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md Ensure hooks only process files that belong to defined workspace roots. Check if the file path starts with any of the provided workspace roots. ```typescript import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'afterFileEdit'> = (payload) => { // Check which workspace the file belongs to const belongsToWorkspace = payload.workspace_roots.some((root) => payload.file_path.startsWith(root) ) if (!belongsToWorkspace) { return {} // Skip files outside workspaces } // Find which workspace const workspace = payload.workspace_roots.find((root) => payload.file_path.startsWith(root) ) console.log(`Processing file in workspace: ${workspace}`) return {} } ``` -------------------------------- ### Test with Local Repository Path Source: https://github.com/beautyfree/cursor-hook/blob/main/DEVELOPMENT.md Test the CLI using a local directory for the hook. This can be done with relative or absolute paths. ```bash # From cursor-hook-cli directory npm run dev install ../cursor-window-activate-hook # Or with absolute path npm run dev install /Users/devall/Projects/orgs/beautyfree/cursor-window-activate-hook ``` -------------------------------- ### Multiple Hooks with Injected Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Illustrates how environment variables are injected separately for each hook command in the final `hooks.json`. ```json { "hooks": { "afterFileEdit": [ { "command": "FORMATTER_KEY='...' node $HOME/.cursor/hooks/formatter/index.js" } ], "beforeShellExecution": [ { "command": "SECURITY_TOKEN='...' node $HOME/.cursor/hooks/security/check.js" } ] } } ``` -------------------------------- ### Test with Remote GitHub Repository Source: https://github.com/beautyfree/cursor-hook/blob/main/DEVELOPMENT.md Test the CLI by specifying a GitHub repository directly. ```bash npm run dev install beautyfree/cursor-window-activate-hook ``` -------------------------------- ### Unix Home Directory Shorthand Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Uses the '~' shorthand for the user's home directory in a command configuration. ```json { "command": "python ~/.cursor/hooks/script.py" } ``` -------------------------------- ### beforeMCPExecution Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before an MCP (Model Context Protocol) tool is executed. It provides the tool name and its input, along with optional URL and command details. ```APIDOC ## beforeMCPExecution ### Description Fired before an MCP (Model Context Protocol) tool is executed. It provides the tool name and its input, along with optional URL and command details. ### Payload `BeforeMCPExecutionPayload` ### Response `BeforeMCPExecutionResponse` ### Payload Fields #### tool_name (string) - Description: The name of the MCP tool to be executed #### tool_input (unknown) - Description: The input provided to the MCP tool #### url (string) - Optional - Description: The URL associated with the tool execution #### command (string) - Optional - Description: The command associated with the tool execution ``` -------------------------------- ### Windows Home Directory Shorthand Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Uses the '%USERPROFILE%' shorthand for the user's home directory in a command configuration on Windows. ```json { "command": "node %USERPROFILE%\.cursor\hooks\script.js" } ``` -------------------------------- ### SessionStartPayload Interface Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Represents the payload for the 'sessionStart' event. It extends HookPayloadBase and includes session-specific details like session ID and composer mode. ```typescript interface SessionStartPayload extends HookPayloadBase { hook_event_name: 'sessionStart' session_id: string is_background_agent: boolean composer_mode?: 'agent' | 'ask' | 'edit' } ``` -------------------------------- ### Manage Hook State Using Files Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md Implement stateful hooks by persisting state to a file. Use `fs.readFileSync` to load state and `fs.writeFileSync` to save it across hook invocations. ```typescript import type { HookHandler } from 'cursor-hook' import * as fs from 'fs' import * as path from 'path' const stateFile = path.join(process.env.HOME ?? '.', '.cursor-hook-state.json') function getState(): Record { try { return JSON.parse(fs.readFileSync(stateFile, 'utf-8')) } catch { return {} } } function setState(state: Record): void { fs.writeFileSync(stateFile, JSON.stringify(state, null, 2)) } const handler: HookHandler<'sessionStart'> = (payload) => { const state = getState() state.lastSession = new Date().toISOString() state.sessionCount = (state.sessionCount ?? 0) + 1 setState(state) return { continue: true } } ``` -------------------------------- ### beforeShellExecution Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before shell commands are executed, allowing you to approve, deny, or ask about execution. It provides details about the command and its working directory. ```APIDOC ## beforeShellExecution ### Description Fired before shell commands are executed, allowing you to approve, deny, or ask about execution. It provides details about the command and its working directory. ### Payload `BeforeShellExecutionPayload` ### Response `BeforeShellExecutionResponse` ### Payload Fields #### command (string) - Description: The shell command to be executed #### cwd (string) - Description: Working directory for execution #### timeout (number) - Optional - Description: Timeout in seconds (if set) ### Request Example ```ts import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'beforeShellExecution'> = (payload) => { if (payload.command.includes('rm -rf')) { return { permission: 'deny', userMessage: 'Dangerous command blocked', } } return { permission: 'allow' } } ``` ``` -------------------------------- ### PreCompactPayload and Response Interfaces Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Interfaces for the preCompact hook, triggered before conversation context is compacted. ```typescript interface PreCompactPayload extends HookPayloadBase { hook_event_name: 'preCompact' trigger: 'auto' | 'manual' context_usage_percent: number context_tokens: number context_window_size: number message_count: number messages_to_compact: number is_first_compaction: boolean } interface PreCompactResponse { user_message?: string } ``` -------------------------------- ### Add CLI to npm Scripts Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/cli-reference.md Integrate the cursor-hook CLI into your project's package.json scripts for easy execution. ```json { "scripts": { "install-hooks": "cursor-hook install " } } ``` -------------------------------- ### postToolUse Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired after a tool executes successfully, allowing modification of the output. ```APIDOC ## postToolUse ### Description Fired after a tool executes successfully, allowing you to modify the output. ### Payload `PostToolUsePayload` ### Response `PostToolUseResponse` ### Response Fields - **updated_mcp_tool_output** (unknown) - Modified tool output ``` -------------------------------- ### SessionStartResponse Interface Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Defines the expected response structure for 'sessionStart' hook handlers. It allows configuration of environment variables, additional context, and session continuation. ```typescript interface SessionStartResponse { env?: Record additional_context?: string continue?: boolean user_message?: string } ``` -------------------------------- ### preCompact Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before conversation context is compacted (summarized). This hook provides details about the current context and the upcoming compaction. ```APIDOC ## preCompact ### Description Fired before conversation context is compacted (summarized). This hook provides details about the current context and the upcoming compaction. ### Method Not Applicable (Event-driven) ### Endpoint Not Applicable (Event-driven) ### Payload `PreCompactPayload` #### Payload Fields - **hook_event_name** (string) - Must be 'preCompact' - **trigger** ('auto' | 'manual') - Whether compaction was automatic or user-initiated. - **context_usage_percent** (number) - Percentage of context window currently in use. - **context_tokens** (number) - Current number of tokens in context. - **context_window_size** (number) - Total context window size. - **message_count** (number) - Total messages in conversation. - **messages_to_compact** (number) - Number of messages that will be compacted. - **is_first_compaction** (boolean) - Whether this is the first compaction in the session. ### Response `PreCompactResponse` #### Success Response (200) - **user_message** (string) - Optional message to display to the user. #### Response Example ```json { "user_message": "Compacting conversation history to save memory." } ``` ``` -------------------------------- ### Hook Configuration with Timeout Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Register a command with a specified timeout in seconds. This limits the execution time for the hook. ```json { "hooks": { "beforeSubmitPrompt": [ { "command": "node $HOME/.cursor/hooks/validator/validate.js", "timeout": 30 } ] } } ``` -------------------------------- ### PreCompactPayload Type Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Payload for the 'preCompact' hook. Contains information about context usage and compaction. Fired before context is compacted. ```typescript interface PreCompactPayload extends HookPayloadBase { hook_event_name: 'preCompact' trigger: 'auto' | 'manual' context_usage_percent: number context_tokens: number context_window_size: number message_count: number messages_to_compact: number is_first_compaction: boolean } ``` -------------------------------- ### Multiple Hooks with Separate Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Configures multiple hooks, each with its own set of required environment variables, ensuring each hook only receives its specific variables. ```json { "installCommand": "npm install --production && npm run build", "files": { "hooks": ["hooks/formatter", "hooks/security"] }, "hooks": { "afterFileEdit": [ { "command": "node $HOME/.cursor/hooks/formatter/index.js", "requiredEnv": ["FORMATTER_KEY"] } ], "beforeShellExecution": [ { "command": "node $HOME/.cursor/hooks/security/check.js", "requiredEnv": ["SECURITY_TOKEN"] } ] } } ``` -------------------------------- ### BeforeTabFileReadResponse Type Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/types.md Expected response from 'beforeTabFileRead' hook handlers. Specifies permission. ```typescript interface BeforeTabFileReadResponse { permission: 'allow' | 'deny' } ``` -------------------------------- ### Hook with Injected Environment Variables Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/configuration.md Shows how required environment variables are injected into the hook command in the final `hooks.json` configuration. ```json { "hooks": { "afterFileEdit": [ { "command": "API_KEY='...' API_URL='...' node $HOME/.cursor/hooks/dist/analyzer.js" } ] } } ``` -------------------------------- ### beforeSubmitPrompt Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before a prompt is submitted to the agent, allowing for interception or modification of the prompt and its attachments. ```APIDOC ## beforeSubmitPrompt ### Description Fired before a prompt is submitted to the agent, allowing you to intercept or modify the prompt and its attachments. ### Method Not Applicable (Event-driven) ### Endpoint Not Applicable (Event-driven) ### Payload `BeforeSubmitPromptPayload` #### Payload Fields - **hook_event_name** (string) - Must be 'beforeSubmitPrompt' - **prompt** (string) - The user's prompt. - **attachments** (HookAttachment[]) - An array of attachments associated with the prompt. ### Response `BeforeSubmitPromptResponse` #### Success Response (200) - **continue** (boolean) - Whether to continue submitting the prompt. - **user_message** (string) - Optional message to display to the user. ### Request Example ```ts import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'beforeSubmitPrompt'> = (payload) => { if (payload.prompt.includes('secret')) { return { continue: false, user_message: 'Prompts with "secret" are blocked', } } return { continue: true } } ``` ``` -------------------------------- ### Asking for Permission for Unallowed Tools Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/hook-patterns.md Implements a 'beforeMCPExecution' hook to ask for user permission if the tool name is not in an allowed list. ```typescript import type { HookHandler } from 'cursor-hook' const handler: HookHandler<'beforeMCPExecution'> = (payload) => { const allowedTools = ['file_editor', 'bash', 'python'] if (!allowedTools.includes(payload.tool_name)) { return { permission: 'ask', userMessage: `Allow ${payload.tool_name}?`, } } return { permission: 'allow' } } ``` -------------------------------- ### beforeReadFile Source: https://github.com/beautyfree/cursor-hook/blob/main/_autodocs/api-reference.md Fired before a file is read, allowing you to block access. It provides the file path, content, and any attachments. ```APIDOC ## beforeReadFile ### Description Fired before a file is read, allowing you to block access. It provides the file path, content, and any attachments. ### Payload `BeforeReadFilePayload` ### Response `BeforeReadFileResponse` ### Payload Fields #### file_path (string) - Description: The path of the file to be read #### content (string) - Description: The content of the file #### attachments (HookAttachment[]) - Description: Attachments associated with the file read operation ### Response Fields #### permission ('allow' | 'deny') - Description: Permission to allow or deny file reading #### user_message (string) - Optional - Description: A message to display to the user if access is denied ```