Хуки Cursor: повний посібник і чому вони іноді не спрацьовують

Хуки Cursor дають змогу скрипту стежити за діями агента або блокувати їх: кожну shell-команду, виклик MCP, читання й редагування файлу. Це потужний інструмент, і ламається він непомітно. Тут зібрано все, що ми дізналися, налаштовуючи їх у реальній роботі.

Автор: Aslan, команда Pet Island · Оновлено 26 жовт. 2026 р. · 7 хв читання

КОРОТКО

Помістіть hooks.json з "version": 1 у ~/.cursor/ (для всіх проєктів) або в .cursor/ у репозиторії, призначте кожній події команду й виводьте JSON у stdout. Використовуйте beforeShellExecution і beforeMCPExecution, щоб дозволяти, забороняти або питати, і задайте failClosed: true, якщо зламаний хук має блокувати команду, а не пропускати її. Якщо хук ніби ігнорується, спершу відкрийте канал виведення Hooks: найчастіше проблема в шляху, у недовіреній робочій області, у некоректному JSON або в події, яку Cursor CLI поки не надсилає.

Що таке хуки Cursor

Хук — це команда, яку Cursor запускає в певній точці циклу агента. Cursor передає на стандартне введення команди об’єкт JSON з описом того, що зараз станеться, чекає і читає відповідь JSON з її стандартного виведення. Одні хуки лише спостерігають (записують редагування в лог, форматують файл). Інші ухвалюють рішення: хук beforeShellExecution може дозволити команді виконатися, зупинити її або спершу спитати вас.

Тому хуки підходять для трьох задач: захисні обмеження (ніколи не запускати rm -rf чи git push --force без людини), автоматизація (форматувати або перевіряти лінтером після кожного редагування) і спостережуваність (записувати або пересилати дії агента, щоб ви знали, коли потрібні йому).

Де розміщується hooks.json

Cursor читає хуки з чотирьох місць і запускає їх усі. Виконується кожен відповідний хук з кожного джерела, а Cursor об’єднує їхні відповіді.

РівеньФайлПримітки
Користувач~/.cursor/hooks.jsonДіє в усіх проєктах. Відносні команди розв’язуються від ~/.cursor/.
Проєкт<project>/.cursor/hooks.jsonЗберігається в репозиторії. Працює лише в довіреній робочій області. Відносні команди розв’язуються від кореня проєкту.
КомандаВебпанель CursorЛише Enterprise, синхронізується в усіх учасників.
EnterpriseC:\ProgramData\Cursor\hooks.json (Windows), /Library/Application Support/Cursor/hooks.json (macOS), /etc/cursor/hooks.json (Linux, WSL)Керується IT-відділом.

Якщо відповіді розходяться, перемагає найсуворіша: deny з будь-якого джерела важливіший за ask, а ask важливіший за allow. Мінімальний робочий файл має такий вигляд (це приклад із документації Cursor):

~/.cursor/hooks.jsonКопіювати
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": "./hooks/format.sh" }]
}
}

version має дорівнювати 1. Cursor стежить за файлом і перезавантажує його під час збереження. Якщо зміна не застосувалася, перезапустіть Cursor. Лише це розв’язує напрочуд багато проблем, про які пишуть на форумі.

Події, на які можна повісити хук

Актуальний список із документації Cursor, згрупований за призначенням:

ГрупаПодіїМоже блокувати?
Shell і MCPbeforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecutionДва хуки before…: дозволити, заборонити або спитати
Будь-який інструментpreToolUse, postToolUse, postToolUseFailurepreToolUse: дозволити або заборонити (ask зараз не застосовується)
ФайлиbeforeReadFile, afterFileEditbeforeReadFile: дозволити або заборонити
ПромптbeforeSubmitPromptТак, з continue: false
Цикл агентаstop, afterAgentResponse, afterAgentThought, preCompactНі (stop може надіслати додаткове повідомлення)
СубагентиsubagentStart, subagentStopsubagentStart: дозволити або заборонити (ask вважається забороною)
Сесія і застосунокsessionStart, sessionEnd, workspaceOpenНі
Автодоповнення TabbeforeTabFileRead, afterTabFileEditbeforeTabFileRead: дозволити або заборонити

Кожна подія отримує кілька спільних полів (conversation_id, generation_id, model, hook_event_name, cursor_version, workspace_roots) і свої власні. beforeShellExecution отримує повну command і її cwd; stop отримує status зі значенням completed, aborted або error.

Дозволити, заборонити або спитати

Хук, що ухвалює рішення, виводить один об’єкт JSON. Для shell-хука це має такий вигляд:

stdout хука beforeShellExecutionКопіювати
{
"permission": "ask",
"user_message": "This pushes to main. Run it?",
"agent_message": "The user wants to confirm pushes."
}
  • permission приймає значення allow, deny або ask.
  • user_message — це те, що ви бачите в Cursor.
  • agent_message — це те, що повідомляється агенту, щоб він змінив курс, а не повторював ту саму команду.

Коди виходу важать не менше, ніж JSON. Код 0 означає «використай мій JSON». Код 2 блокує дію так само, як deny. Будь-який інший код виходу вважається збоєм хука, і дія виконується, якщо не задано failClosed. Для хуків дозволів некоректний JSON або JSON, що не відповідає схемі, блокує дію.

Документація Cursor зазначає, що ask підтримується для beforeShellExecution і beforeMCPExecution. У березні 2026 року співробітники Cursor написали на форумі, що хуки застосовували лише deny, а allow і ask «basically ignored» (по суті ігнорувалися), особливо з увімкненим списком дозволених команд або пісочницею. Оголошення про виправлення ми не знайшли. Якщо захист має спрацьовувати гарантовано, повертайте deny, а не ask, і перевірте це у своїй версії.

failClosed і timeout

Кожен запис хука поруч із command може мати параметри:

.cursor/hooks.jsonКопіювати
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{
"command": "./.cursor/hooks/guard.sh",
"timeout": 30,
"failClosed": true
}
]
}
}
  • failClosed: true перетворює збій, тайм-аут, ненульовий код виходу або порожнє виведення на блокування. За замовчуванням false: зламаний захисний хук мовчки пропускає все. Для хука безпеки майже завжди потрібно true.
  • timeout задається в секундах. Залиште достатній запас, якщо хук чекає на людину: тому, хто читає diff, потрібно більше п’яти секунд.
  • matcher визначає, коли запускається хук. Для shell-хуків він порівнюється з повним рядком команди, для хуків інструментів з типом інструмента, наприклад Shell, Read, Write або MCP:<tool_name>.

Тут є компроміс. У липні 2026 року користувач macOS натрапив на помилку «MainThreadShellExec not initialized»: власний shell-хост Cursor ще не був готовий, і оскільки хук працював у режимі fail-closed, shell агента виявився заблокованим. Співробітники Cursor повідомили, що виправлення вже вийшло, і рекомендували залишити failClosed: true. Якщо ви бачите цю помилку в старій збірці, обхідним рішенням була команда «Developer: Reload Window».

Хуки у Windows

У Windows настільний застосунок Cursor запускає команди хуків через PowerShell і передає їм JSON конвеєром. Скрипт PowerShell читає його з $input; будь-яка інша програма читає стандартне введення як зазвичай. Спотикаються на трьох речах:

  1. Bash-скрипти не запускаються як є. guard.sh від колеги на macOS падає в PowerShell. Використовуйте скрипт .ps1, скомпільовану програму або явно викликайте інтерпретатор (python .cursor/hooks/guard.py). В обговоренні на форумі від січня 2026 року конфігурація з Git Bash падає з помилкою syntax error near unexpected token '[Convert]::FromBase64String', тобто код PowerShell потрапляє в bash.
  2. Політика виконання. Якщо PowerShell відмовляється запускати скрипти, запускайте їх командою powershell -NoProfile -ExecutionPolicy Bypass -File …, виводьте JSON і завершуйте exit 0.
  3. Програми з GUI повертаються надто рано. Це коштувало нам цілого дня. Якщо хук — програма Windows, зібрана для підсистеми GUI, PowerShell запускає її і йде далі, не чекаючи завершення. Cursor читає порожнє виведення, тому здається, що хук нічого не зробив (або, з failClosed, блокує все). Зберіть хук як консольну програму або оберніть його так, щоб PowerShell чекав на його завершення.

Хукам рівня проєкту також потрібна довірена робоча область. Співробітник Cursor перелічив, що перевірити, якщо вони нічого не роблять: рядок у журналі Hooks «Hook N produced no output», позначку про довірену робочу область у Settings → Hooks і помилки на кшталт spawn, ENOENT, EPERM або ExecutionPolicy у консолі.

Хуки в Cursor CLI

Cursor CLI (cursor-agent) читає ті самі ~/.cursor/hooks.json і .cursor/hooks.json, але ніколи не надсилав усіх подій, які надсилає редактор. У січні 2026 року спрацьовували лише два shell-хуки. До квітня співробітники Cursor підтвердили, що в CLI працюють beforeShellExecution, afterShellExecution, afterFileEdit, postToolUse, stop і sessionStart, а afterAgentResponse і afterAgentThought досі ні (повторно підтверджено в травні). Будь-яку подію не з цього списку перевірте, перш ніж на неї покладатися.

Хмарні агенти ще суворіші: користувацькі хуки з ~/.cursor/hooks.json там узагалі не запускаються.

Коли хук не спрацьовує: чек-лист

  1. Відкрийте канал виведення Hooks (View → Output → Hooks) або вкладку Hooks у Customize. Там видно, які хуки завантажилися, кожен запуск і помилки.
  2. Перевірте сам файл JSON. Є "version": 1, назви подій написано точно (вони чутливі до регістру), JSON коректний.
  3. Перевірте шлях. Відносні команди розв’язуються від кореня проєкту для хуків проєкту і від ~/.cursor/ для користувацьких хуків.
  4. Позначте робочу область як довірену. Хуки проєкту не запускаються в недовіреній папці.
  5. Запустіть хук вручну. Передайте йому на вхід приклад JSON і подивіться на stdout. Усе, крім одного об’єкта JSON (випадковий echo, попередження), ламає розбір.
  6. Перезапустіть Cursor. Під час збереження файл перезавантажується, але в кількох випадках із форуму допоміг лише повний перезапуск.
  7. Знайте про прогалини. Повідомлялося, що ask і allow ігноруються за наявності списку дозволених команд і пісочниці; що subagentStart/subagentStop у деяких версіях не спрацьовують; CLI пропускає частину подій. Коміти з вбудованої панелі Source Control не перехоплюються: події хука pre-commit немає.

Хуки, auto-run і Auto-review

Хуки працюють окремо від власних налаштувань підтвердження Cursor (Settings → Agents → Approvals & Execution). Auto-run і Auto-review визначають, чи спитає вас Cursor у своїй панелі; ваш хук додає поверх своє рішення. Тому скарга «мій хук сказав ask, а команда просто виконалася» трапляється так часто: її вже дозволив інший механізм дозволів.

Ще одне, що ми дізналися на власному досвіді: з Auto-review Cursor може спитати про деякі команди у своєму вікні. Хук цього запитання ніколи не бачить. Воно виникає всередині Cursor, а не в конвеєрі хуків.

Де тут Pet Island

Якщо від хуків вам потрібно «показуй кожну ризиковану команду й дай вирішити, не перемикаючи вікон», саме це Pet Island і робить із Cursor. Він сам встановлює хуки (beforeShellExecution і beforeMCPExecution, з увімкненим failClosed, щоб помічник, що впав, ніколи не пропустив команду) і виводить кожен запит на маленький острів у верхній частині екрана з повною командою. Ви дозволяєте або забороняєте його там; власний агент Cursor чекає.

Команди й редагування файлів з редактора Cursor працюють з острова. Запитання і плани показуються на острові, а відповідаєте ви на них у Cursor. У Cursor CLI команди працюють з острова; решта подій залежить від того, що надсилає CLI. Під час видалення прибираються лише записи, додані Pet Island; ваші власні хуки залишаються.

Поширені запитання

Чи працюють хуки Cursor у Windows?

Так. Настільний застосунок запускає їх через PowerShell і передає JSON на стандартне введення ($input у скрипті PowerShell). Bash-скриптам, написаним для macOS, потрібна версія на PowerShell або Python, а програми підсистеми GUI треба обгортати, щоб PowerShell чекав на їхнє завершення.

Чому хук повертає ask, а команда однаково виконується?

У березні 2026 року співробітники Cursor повідомили, що хуки надійно застосовували лише deny; allow і ask могли перевизначатися списком дозволених команд або пісочницею. Використовуйте deny для всього, що не повинно виконуватися, і перевіряйте в каналі виведення Hooks, що насправді повернув хук.

Що робить failClosed?

Якщо failClosed дорівнює true, збій, тайм-аут, ненульовий код виходу або порожнє виведення блокують дію. Без нього зламаний хук пропускає дію.

Де подивитися помилки хуків?

У каналі виведення Hooks (View → Output → Hooks) і на вкладці Hooks у Customize.

Чи працюють хуки в Cursor CLI?

Частково. CLI читає ті самі файли hooks.json. Станом на травень 2026 року співробітники Cursor підтвердили shell-хуки, afterFileEdit, postToolUse, stop і sessionStart, але не afterAgentResponse і afterAgentThought.

Чи може хук зупинити git-коміт із панелі Source Control?

Ні. У Cursor немає події хука pre-commit, і коміти через вбудований інтерфейс Source Control не перехоплюються. Для цього використовуйте звичайний git-хук pre-commit.

Джерела

Усі налаштування й описану поведінку на цій сторінці звірено з цими джерелами 26 жовтня 2026 р.. Агенти швидко змінюються; якщо щось уже не збігається, пріоритет має офіційна сторінка.

ЧИТАЙТЕ ТАКОЖ

Відповідайте будь-якому агенту просто з верхньої частини екрана.

Windows і Mac · 7 днів безплатно, потім $8.99 одноразово · $1 з кожного продажу йде на корм безпритульним тваринам

Спробувати Pet Island безплатно