Cursor hook'ları: eksiksiz rehber ve bazen neden tetiklenmiyorlar

Cursor hook'ları, bir script'in ajanın yaptıklarını izlemesine veya engellemesine izin verir: her shell komutu, MCP çağrısı, dosya okuma ve düzenleme. Güçlüdürler, ama bozulduklarında bunu sessizce yaparlar. Bunları gerçekten kurarken öğrendiğimiz her şey burada.

Aslan, Pet Island ekibi · Güncellendi: 26 Eki 2026 · 7 dk okuma

KISA CEVAP

~/.cursor/ (tüm projeler) veya bir repodaki .cursor/ klasörüne "version": 1 içeren bir hooks.json koy, her event'i bir komuta yönlendir ve stdout'a JSON yazdır. İzin vermek, reddetmek veya sormak için beforeShellExecution ve beforeMCPExecution kullan; bozuk bir hook'un komutu geçirmek yerine engellemesi gerekiyorsa failClosed: true ayarla. Bir hook yok sayılıyor gibi görünüyorsa önce Hooks çıktı kanalını aç: sorunların çoğu bir yol, güvenilmeyen bir çalışma alanı, geçersiz JSON veya Cursor CLI'ın henüz göndermediği bir event'tir.

Cursor hook'ları nedir

Hook, Cursor'ın ajan döngüsünde sabit bir noktada çalıştırdığı bir komuttur. Cursor, olmak üzere olan şeyi anlatan bir JSON nesnesini komutun standart girdisine gönderir, bekler ve standart çıktısından bir JSON cevap okur. Bazı hook'lar sadece gözlemler (düzenlemeyi loglar, dosyayı biçimlendirir). Diğerleri karar verir: bir beforeShellExecution hook'u bir komutun çalışmasına izin verebilir, onu durdurabilir veya önce sana sorabilir.

Bu da hook'ları üç iş için doğru araç yapar: güvenlik bariyerleri (bir insan olmadan asla rm -rf veya git push --force çalıştırmamak), otomasyon (her düzenlemeden sonra biçimlendirme veya lint) ve görünürlük (ajanın yaptıklarını loglamak veya iletmek, böylece sana ne zaman ihtiyaç duyduğunu bilirsin).

hooks.json nerede bulunur

Cursor hook'ları dört yerden okur ve hepsini çalıştırır. Her kaynaktaki eşleşen her hook çalışır ve Cursor cevaplarını birleştirir.

SeviyeDosyaNotlar
Kullanıcı~/.cursor/hooks.jsonHer projeye uygulanır. Göreli komutlar ~/.cursor/ konumuna göre çözülür.
Proje<project>/.cursor/hooks.jsonRepoya commit'lenir. Sadece güvenilen bir çalışma alanında çalışır. Göreli komutlar proje köküne göre çözülür.
EkipCursor web paneliSadece Enterprise, her üyeye senkronize edilir.
EnterpriseC:\ProgramData\Cursor\hooks.json (Windows), /Library/Application Support/Cursor/hooks.json (macOS), /etc/cursor/hooks.json (Linux, WSL)BT tarafından yönetilir.

Cevaplar çeliştiğinde en katı olan kazanır: herhangi bir kaynaktan gelen deny, ask cevabını yener, ask da allow cevabını. Çalışan en küçük dosya şöyle görünür (Cursor dokümanlarındaki örnektir):

~/.cursor/hooks.jsonKopyala
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": "./hooks/format.sh" }]
}
}

version değeri 1 olmalıdır. Cursor dosyayı izler ve kaydettiğinde yeniden yükler. Bir değişiklik etkili olmazsa Cursor'ı yeniden başlat. Sadece bu bile forumdaki şaşırtıcı sayıda şikayeti çözüyor.

Hook bağlayabileceğin event'ler

Cursor dokümanlarındaki güncel liste, ne işe yaradıklarına göre gruplanmış hâliyle:

GrupEvent'lerEngelleyebilir mi?
Shell ve MCPbeforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecutionİki before… hook'u: izin ver, reddet veya sor
Herhangi bir araçpreToolUse, postToolUse, postToolUseFailurepreToolUse: izin ver veya reddet (ask şu anda uygulanmıyor)
DosyalarbeforeReadFile, afterFileEditbeforeReadFile: izin ver veya reddet
PromptbeforeSubmitPromptEvet, continue: false ile
Ajan döngüsüstop, afterAgentResponse, afterAgentThought, preCompactHayır (stop bir takip mesajı gönderebilir)
Alt ajanlarsubagentStart, subagentStopsubagentStart: izin ver veya reddet (ask, deny sayılır)
Oturum ve uygulamasessionStart, sessionEnd, workspaceOpenHayır
Tab tamamlamalarıbeforeTabFileRead, afterTabFileEditbeforeTabFileRead: izin ver veya reddet

Her event birkaç ortak alan (conversation_id, generation_id, model, hook_event_name, cursor_version, workspace_roots) ve kendine özgü alanlar alır. beforeShellExecution tam command değerini ve onun cwd değerini alır; stop ise completed, aborted veya error değerine sahip bir status alır.

İzin vermek, reddetmek ve sormak

Karar veren bir hook tek bir JSON nesnesi yazdırır. Shell hook'u için bu şöyle görünür:

bir beforeShellExecution hook'unun stdout çıktısıKopyala
{
"permission": "ask",
"user_message": "This pushes to main. Run it?",
"agent_message": "The user wants to confirm pushes."
}
  • permission değeri allow, deny veya ask olur.
  • user_message Cursor'da senin gördüğün metindir.
  • agent_message ajana söylenen metindir; böylece aynı komutu yeniden denemek yerine yön değiştirebilir.

Çıkış kodları JSON kadar önemlidir. 0 ile çıkmak “benim JSON'umu kullan” demektir. 2 ile çıkmak, deny ile aynı şekilde işlemi engeller. failClosed ayarlamadıysan diğer her çıkış kodu başarısız bir hook sayılır ve işlem devam eder. İzin hook'larında geçersiz JSON veya şemaya uymayan JSON işlemi engeller.

Cursor'ın dokümanları ask değerini beforeShellExecution ve beforeMCPExecution için destekleniyor olarak listeliyor. Mart 2026'da Cursor çalışanları forumda hook'ların sadece deny cevabını uyguladığını, allow ve ask cevaplarının ise özellikle komut izin listesi veya sandbox açıkken “basically ignored” olduğunu (yani neredeyse yok sayıldığını) yazdı. Bir düzeltme duyurusu bulamadık. Bir güvenlik bariyerinin mutlaka tutması gerekiyorsa ask değil deny döndür ve kendi sürümünde test et.

failClosed ve timeout

Her hook girdisi command alanının yanında seçenekler taşıyabilir:

.cursor/hooks.jsonKopyala
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{
"command": "./.cursor/hooks/guard.sh",
"timeout": 30,
"failClosed": true
}
]
}
}
  • failClosed: true bir çökmeyi, zaman aşımını, sıfır olmayan bir çıkışı veya boş çıktıyı engellemeye dönüştürür. Varsayılan değer false: bozuk bir koruma sessizce her şeyi geçirir. Bir güvenlik hook'u için neredeyse her zaman true istersin.
  • timeout saniye cinsindendir. Hook'un bir insanı bekliyorsa yeterli pay bırak: bir diff okuyan birinin beş saniyeden fazlasına ihtiyacı vardır.
  • matcher hook'un ne zaman çalışacağını filtreler. Shell hook'larında tam komut metniyle, araç hook'larında ise Shell, Read, Write veya MCP:<tool_name> gibi araç türüyle eşleştirilir.

Bunun bir bedeli var. Temmuz 2026'da macOS'taki bir kullanıcı “MainThreadShellExec not initialized” hatasıyla karşılaştı: Cursor'ın kendi shell host'u hazır değildi ve hook fail-closed olduğu için ajanın shell'i engellendi. Cursor çalışanları düzeltmenin yayınlandığını söyledi ve failClosed: true ayarını korumayı önerdi. Bu hatayı eski bir sürümde görürsen geçici çözüm “Developer: Reload Window” idi.

Windows'ta hook'lar

Windows'ta Cursor masaüstü uygulaması hook komutlarını PowerShell üzerinden çalıştırır ve JSON'u içine pipe'lar. Bir PowerShell script'i bunu $input üzerinden okur; diğer programlar standart girdiyi her zamanki gibi okur. Üç şey sık sık sorun çıkarır:

  1. Bash script'leri olduğu gibi çalışmaz. macOS kullanan bir ekip arkadaşından gelen guard.sh PowerShell altında başarısız olur. Bir .ps1 script'i, derlenmiş bir program kullan veya yorumlayıcını açıkça çağır (python .cursor/hooks/guard.py). Ocak 2026 tarihli bir forum konusu, bir Git Bash kurulumunun syntax error near unexpected token '[Convert]::FromBase64String' hatasıyla başarısız olduğunu gösteriyor; bu, bash'e ulaşan PowerShell kodudur.
  2. Execution policy. PowerShell script çalıştırmayı reddediyorsa script'leri powershell -NoProfile -ExecutionPolicy Bypass -File … ile başlat, JSON'u yazdır ve exit 0 ile bitir.
  3. GUI programları çok erken döner. Bu bize bir güne mal oldu. Hook'un GUI alt sistemi için derlenmiş bir Windows programıysa PowerShell onu başlatır ve beklemeden devam eder. Cursor boş çıktı okur, bu yüzden hook hiçbir şey yapmamış gibi görünür (veya failClosed ile her şeyi engeller). Hook'u bir konsol programı olarak derle veya PowerShell'in çıkmasını beklemesi için onu sarmala.

Proje seviyesindeki hook'lar ayrıca güvenilen bir çalışma alanı gerektirir. Bir Cursor çalışanı, hiçbir şey yapmadıklarında kontrol edilecekleri listeledi: Hooks logundaki “Hook N produced no output” satırı, Settings → Hooks altında çalışma alanının güvenilir olarak görünmesi ve konsolda spawn, ENOENT, EPERM veya ExecutionPolicy gibi hatalar.

Cursor CLI'da hook'lar

Cursor CLI (cursor-agent) aynı ~/.cursor/hooks.json ve .cursor/hooks.json dosyalarını okur, ama editörün gönderdiği her event'i hiçbir zaman göndermedi. Ocak 2026'da sadece iki shell hook'u tetikleniyordu. Nisan ayına gelindiğinde Cursor çalışanları beforeShellExecution, afterShellExecution, afterFileEdit, postToolUse, stop ve sessionStart event'lerinin CLI'da çalıştığını, afterAgentResponse ve afterAgentThought event'lerinin ise hâlâ çalışmadığını doğruladı (mayısta tekrar doğrulandı). Bu listede olmayan herhangi bir event için: ona güvenmeden önce test et.

Bulut ajanları daha da katıdır: ~/.cursor/hooks.json dosyasındaki kullanıcı seviyesi hook'lar orada hiç çalışmaz.

Bir hook tetiklenmediğinde: kontrol listesi

  1. Hooks çıktı kanalını aç (View → Output → Hooks) veya Customize içindeki Hooks sekmesini. Hangi hook'ların yüklendiğini, her çalışmayı ve hataları gösterir.
  2. JSON dosyasının kendisini kontrol et. "version": 1 mevcut olmalı, event adları tam olarak doğru yazılmalı (büyük/küçük harfe duyarlıdır) ve JSON geçerli olmalı.
  3. Yolu kontrol et. Göreli komutlar proje hook'larında proje köküne, kullanıcı hook'larında ~/.cursor/ konumuna göre çözülür.
  4. Çalışma alanına güven. Proje hook'ları güvenilmeyen bir klasörde çalışmaz.
  5. Hook'u elle çalıştır. İçine örnek bir JSON pipe'la ve stdout'a bak. Tek bir JSON nesnesi dışındaki her şey (başıboş bir echo, bir uyarı) ayrıştırmayı bozar.
  6. Cursor'ı yeniden başlat. Kaydetmek dosyayı yeniden yükler, ama birkaç forum şikayeti ancak tam bir yeniden başlatmayla çözüldü.
  7. Bilinen eksikleri unutma. ask ve allow cevaplarının izin listesi ve sandbox yanında yok sayıldığı bildirildi; subagentStart/subagentStop event'lerinin bazı sürümlerde tetiklenmediği bildirildi; CLI bazı event'leri atlar. Yerleşik Source Control panelinden yapılan commit'ler yakalanmaz: pre-commit hook event'i yoktur.

Hook'lar, auto-run ve Auto-review

Hook'lar Cursor'ın kendi onay ayarlarından (Settings → Agents → Approvals & Execution) ayrıdır. Auto-run ve Auto-review, Cursor'ın sana kendi panelinde sorup sormayacağına karar verir; hook'un bunun üstüne kendi kararını ekler. “Hook'um ask dedi ama komut doğrudan çalıştı” şikayetinin bu kadar yaygın olmasının sebebi budur: başka bir izin yolu ona zaten izin vermiştir.

Zor yoldan öğrendiğimiz bir şey daha: Auto-review ile Cursor bazı komutları kendi penceresinde sorabilir. Bir hook bu soruyu asla görmez. Bu, hook hattında değil Cursor'ın içinde olur.

Pet Island'ın yeri

Hook'lardan istediğin “her riskli komutu bana göster ve pencere değiştirmeden karar vermemi sağla” ise Pet Island'ın Cursor ile yaptığı tam olarak budur. Hook'ları senin için kurar (beforeShellExecution ve beforeMCPExecution, failClosed açık şekilde, böylece çökmüş bir yardımcı asla bir komutu geçirmez) ve her isteği tam komutla birlikte ekranının üstündeki küçük bir adaya koyar. Orada izin verir veya reddedersin; Cursor'ın kendi ajanı bekler.

Cursor editöründen gelen komutlar ve dosya düzenlemeleri adadan çalışır. Sorular ve planlar adada görünür, onlara Cursor'da cevap verirsin. Cursor CLI'da komutlar adadan çalışır; diğer event'ler CLI'ın ne gönderdiğine bağlıdır. Kaldırma işlemi sadece Pet Island'ın eklediği girdileri siler; kendi hook'ların kalır.

SSS

Cursor hook'ları Windows'ta çalışır mı?

Evet. Masaüstü uygulaması onları PowerShell üzerinden çalıştırır ve JSON'u standart girdiden iletir (PowerShell script'inde $input). macOS için yazılmış Bash script'lerinin PowerShell veya Python sürümü gerekir ve GUI alt sistemi programları PowerShell onları beklesin diye sarmalanmalıdır.

Hook'um ask döndürüyor ama komut yine de neden çalışıyor?

Cursor çalışanları Mart 2026'da hook'ların sadece deny cevabını güvenilir şekilde uyguladığını söyledi; allow ve ask, izin listesi veya sandbox tarafından geçersiz kılınabiliyordu. Kesinlikle çalışmaması gereken her şey için deny kullan ve hook'unun gerçekte ne döndürdüğünü görmek için Hooks çıktı kanalına bak.

failClosed ne işe yarar?

failClosed true olarak ayarlandığında bir çökme, zaman aşımı, sıfır olmayan çıkış veya boş çıktı işlemi engeller. Bu ayar olmadan bozuk bir hook işlemin devam etmesine izin verir.

Hook hatalarını nerede görürüm?

Hooks çıktı kanalında (View → Output → Hooks) ve Customize içindeki Hooks sekmesinde.

Hook'lar Cursor CLI'da çalışır mı?

Kısmen. CLI aynı hooks.json dosyalarını okur. Mayıs 2026 itibarıyla Cursor çalışanları shell hook'larını, afterFileEdit, postToolUse, stop ve sessionStart event'lerini doğruladı; afterAgentResponse ve afterAgentThought ise çalışmıyor.

Bir hook, Source Control panelinden yapılan bir git commit'ini durdurabilir mi?

Hayır. Cursor'da pre-commit hook event'i yoktur ve yerleşik Source Control arayüzünden yapılan commit'ler yakalanmaz. Bunun için normal bir git pre-commit hook'u kullan.

Kaynaklar

Bu sayfadaki her ayar ve davranış 26 Ekim 2026 tarihinde bu sayfalarla karşılaştırılarak kontrol edildi. Ajanlar hızlı değişir; bir şey artık uyuşmuyorsa geçerli olan resmi sayfadır.

OKUMAYA DEVAM ET

Tüm ajanlarına ekranının üstünden cevap ver.

Windows ve Mac · 7 gün ücretsiz, sonra tek seferlik $8.99 · Her satıştan $1 sokak hayvanlarını besler

Pet Island'ı ücretsiz dene