Özel ilkeler, herhangi bir ajan davranışı için kurallar yazmanızı sağlar: proje kurallarını uygulayın, sapmaları önleyin, yıkıcı işlemleri engelleyin, takılı kalan ajanları algılayın veya Slack, onay iş akışları ve daha fazlasıyla entegre olun. Yerleşik ilkelerle aynı hook olay sistemini ve allow, deny, instruct kararlarını kullanırlar.
Hızlı örnek
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add({
name: "no-production-writes",
description: "Block writes to paths containing 'production'",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Write" && ctx.toolName !== "Edit") return allow();
const path = ctx.toolInput?.file_path ?? "";
if (path.includes("production")) {
return deny("Writes to production paths are blocked");
}
return allow();
},
});
Kurun:
failproofai policies --install --custom ./my-policies.js
Özel ilkeleri yüklemenin iki yolu
Seçenek 1: Kural tabanlı (önerilen)
*policies.{js,mjs,ts} dosyalarını .failproofai/policies/ dizinine koyun ve otomatik olarak yüklenir — herhangi bir bayrak veya yapılandırma değişikliğine gerek yoktur. Bu git hook’lar gibi çalışır: dosya koyun, işte olur.
# Proje seviyesi — git'e gönderilen, ekip ile paylaşılan
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs
# Kullanıcı seviyesi — kişisel, tüm projeler için geçerli
~/.failproofai/policies/my-policies.mjs
Nasıl çalışır:
- Hem proje hem de kullanıcı dizinleri taranır (birleşim — ilk-başarı-kazanır değil)
- Dosyalar her dizin içinde alfabetik sırayla yüklenir. Sırayı kontrol etmek için
01-, 02- ön ekini kullanın
- Yalnızca
*policies.{js,mjs,ts} ile eşleşen dosyalar yüklenir; diğer dosyalar yoksayılır
- Her dosya bağımsız olarak yüklenir (dosya başına açık başarısız)
- Açık
--custom ve yerleşik ilkelerle birlikte çalışır
Kural tabanlı ilkeler, kuruluşunuz için bir kalite standardı oluşturmanın en kolay yoludur. .failproofai/policies/ dizinini git’e gönderün ve her ekip üyesi otomatik olarak aynı kurallara sahip olur — geliştirici başına kurulum gerekmez. Ekibiniz yeni hata modlarını keşfettikçe, bir ilke ekleyin ve gönderin. Zamanla bunlar, her katkıyla iyileşmeye devam eden canlı bir kalite standardı haline gelir.
Seçenek 2: Açık dosya yolu
# Özel ilkeler dosyasıyla kurun
failproofai policies --install --custom ./my-policies.js
# İlkeler dosyası yolunu değiştirin
failproofai policies --install --custom ./new-policies.js
# Yapılandırmadan özel ilkeler yolunu kaldırın
failproofai policies --uninstall --custom
Çözülmüş mutlak yol, customPoliciesPath olarak policies-config.json içinde depolanır. Dosya her hook olayında yeni yüklenir - olaylar arasında önbellekleme yoktur.
Her ikisini birlikte kullanma
Kural tabanlı ilkeler ve açık --custom dosyası birlikte bulunabilir. Yükleme sırası:
- Açık
customPoliciesPath dosyası (yapılandırılmışsa)
- Proje kural tabanlı dosyaları (
{cwd}/.failproofai/policies/, alfabetik)
- Kullanıcı kural tabanlı dosyaları (
~/.failproofai/policies/, alfabetik)
API
İçeri Aktarma
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add(hook)
Bir ilkeyi kaydeder. Aynı dosyada birden fazla ilke için gerektiği kadar çağırın.
customPolicies.add({
name: string; // gerekli - benzersiz tanımlayıcı
description?: string; // `failproofai policies` çıkışında gösterilir
match?: { events?: HookEventType[] }; // olay türüne göre filtrele; hepsini eşleştirmek için çıkar
fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});
Karar yardımcıları
| İşlev | Etki | Kullanım zamanı |
|---|
allow() | İşleme sessizce izin ver | İşlem güvenli, mesaj gerekli değil |
deny(message) | İşlemi engelle | Ajan bu işlemi yapmamalı |
instruct(message) | Engellemeden bağlam ekle | Ajana takılı kalmamak için ekstra bağlam ver |
deny(message) - mesaj Claude’a "Blocked by failproofai:" önekiyle gösterilir. Tek bir deny, tüm daha sonraki değerlendirmeleri kısa devre yapar.
instruct(message) - mesaj, geçerli araç çağrısı için Claude’un bağlamına eklenir. Tüm instruct mesajları biriktirilir ve birlikte teslim edilir.
Kod değişikliği yapılmadan herhangi bir deny veya instruct mesajına policyParams içinde bir hint alanı ekleyerek ek rehberlik ekleyebilirsiniz — bu özel (custom/), proje kural tabanlı (.failproofai-project/), ve kullanıcı kural tabanlı (.failproofai-user/) ilkeler için de çalışır. Ayrıntılar için Yapılandırma → hint bölümüne bakın.
Bilgilendirici izin mesajları
allow(message) işleme izin verir ve Claude’a bir bilgilendirici mesaj geri gönderir. Mesaj, hook işleyicisinin stdout yanıtında additionalContext olarak teslim edilir — instruct ile aynı mekanizma kullanılır, ancak anlamsal olarak farklıdır: uyarı değil, bir durum güncellemesidir.
| İşlev | Etki | Kullanım zamanı |
|---|
allow(message) | İzin ver ve Claude’a bağlam gönder | Kontrolün geçtiğini onaylayın veya kontrolün neden atlandığını açıklayın |
Kullanım örnekleri:
- Durum onayları:
allow("All CI checks passed.") — Claude’a her şeyin yeşil olduğunu söyler
- Açık başarısızlık açıklamaları:
allow("GitHub CLI not installed, skipping CI check.") — Claude’a kontrolün neden atlandığını söyler böylece tam bağlama sahip olur
- Birden fazla mesaj birikiyor: birkaç ilke her biri
allow(message) döndürürse, tüm mesajlar yeni satırlarla birleştirilir ve birlikte teslim edilir
customPolicies.add({
name: "confirm-branch-status",
match: { events: ["Stop"] },
fn: async (ctx) => {
const cwd = ctx.session?.cwd;
if (!cwd) return allow("No working directory, skipping branch check.");
// ... şube durumunu kontrol et ...
if (allPushed) {
return allow("Branch is up to date with remote.");
}
return deny("Unpushed changes detected.");
},
});
PolicyContext alanları
| Alan | Tür | Açıklama |
|---|
eventType | string | "PreToolUse", "PostToolUse", "Notification", "Stop" |
toolName | string | undefined | Çağrılan araç (örneğin "Bash", "Write", "Read") |
toolInput | Record<string, unknown> | undefined | Aracın giriş parametreleri |
payload | Record<string, unknown> | Claude Code’dan gelen tam ham olay yükü |
session | SessionMetadata | undefined | Oturum bağlamı (aşağıya bakın) |
| Alan | Tür | Açıklama |
|---|
sessionId | string | Claude Code oturum tanımlayıcısı |
cwd | string | Claude Code oturumunun çalışma dizini |
transcriptPath | string | Oturumun JSONL transkript dosyasının yolu |
Olay türleri
| Olay | Ne zaman çalışır | toolInput içeriği |
|---|
PreToolUse | Claude bir araç çalıştırmadan önce | Aracın girişi (örneğin Bash için { command: "..." }) |
PostToolUse | Bir araç tamamlandıktan sonra | Aracın girişi + tool_result (çıkış) |
Notification | Claude bir bildirim gönderdiğinde | { message: "...", notification_type: "idle" | "permission_prompt" | ... } - hook’lar her zaman allow() döndürmelidir, bildirim’leri engelleyemezler |
Stop | Claude oturumu sona erdiğinde | Boş |
Değerlendirme sırası
İlkeler bu sırayla değerlendirilir:
- Yerleşik ilkeler (tanım sırasında)
customPoliciesPath dan gelen açık özel ilkeler (.add() sırasında)
- Proje
.failproofai/policies/ den gelen kural tabanlı ilkeler (dosyalar alfabetik, içinde .add() sırasında)
- Kullanıcı
~/.failproofai/policies/ den gelen kural tabanlı ilkeler (dosyalar alfabetik, içinde .add() sırasında)
İlk deny tüm sonraki ilkeleri kısa devre yapar. Tüm instruct mesajları biriktirilir ve birlikte teslim edilir.
Geçişli içeri aktarmalar
Özel ilke dosyaları bağıl yollar kullanarak yerel modülleri içeri aktarabilir:
// my-policies.js
import { isBlockedPath } from "./utils.js";
import { checkApproval } from "./approval-client.js";
customPolicies.add({
name: "approval-gate",
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const approved = await checkApproval(ctx.toolInput?.command, ctx.session?.sessionId);
return approved ? allow() : deny("Approval required for this command");
},
});
Giriş dosyasından ulaşılabilen tüm bağıl içeri aktarmalar çözülür. Bu, from "failproofai" içeri aktarmalarını gerçek dist yoluna yeniden yazarak ve ESM uyumluluğunu sağlamak için geçici .mjs dosyaları oluşturarak uygulanır.
Olay türü filtrelemesi
Bir ilkenin ne zaman çalışacağını sınırlamak için match.events kullanın:
customPolicies.add({
name: "require-summary-on-stop",
match: { events: ["Stop"] },
fn: async (ctx) => {
// Yalnızca oturum sona erdiğinde çalışır
// ctx.session.transcriptPath tam oturum günlüğünü içerir
return allow();
},
});
Her olay türünde çalışması için match tamamen çıkarın.
Hata işleme ve başarısızlık modları
Özel ilkeler açık başarısızlık: hatalar asla yerleşik ilkeleri engellemeyen veya hook işleyiciyi kıramaz.
| Başarısızlık | Davranış |
|---|
customPoliciesPath ayarlanmamış | Açık özel ilkeler çalışmaz; kural tabanlı ilkeler ve yerleşik olanlar normal devam eder |
| Dosya bulunamadı | Uyarı ~/.failproofai/hook.log dosyasına kaydedilir; yerleşik olanlar devam eder |
| Söz dizimi/içeri aktarma hatası (açık) | Hata ~/.failproofai/hook.log dosyasına kaydedilir; açık özel ilkeler atlanır |
| Söz dizimi/içeri aktarma hatası (kural tabanlı) | Hata kaydedilir; bu dosya atlanır, diğer kural tabanlı dosyalar yüklenir |
fn çalışma zamanında hata atarsa | Hata kaydedilir; bu hook allow olarak işlenir; diğer hook’lar devam eder |
fn 10 saniyeden daha uzun sürerse | Zaman aşımı kaydedilir; allow olarak işlenir |
| Kural tabanlı dizin eksikse | Kural tabanlı ilkeler çalışmaz; hata yok |
Özel ilke hatalarını hata ayıklamak için günlük dosyasını izleyin:tail -f ~/.failproofai/hook.log
Tam örnek: birden fazla ilke
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
// Ajanın secrets/ dizinine yazmasını engelle
customPolicies.add({
name: "block-secrets-dir",
description: "Prevent agent from writing to secrets/ directory",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
const path = ctx.toolInput?.file_path ?? "";
if (path.includes("secrets/")) return deny("Writing to secrets/ is not permitted");
return allow();
},
});
// Ajanı takılı tutun: göndermeden önce testleri doğrula
customPolicies.add({
name: "remind-test-before-commit",
description: "Keep the agent on track: verify tests pass before committing",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const cmd = ctx.toolInput?.command ?? "";
if (/git\s+commit/.test(cmd)) {
return instruct("Verify all tests pass before committing. Run `bun test` if you haven't already.");
}
return allow();
},
});
// Dondurma döneminde planlanmamış bağımlılık değişikliklerini önle
customPolicies.add({
name: "dependency-freeze",
description: "Prevent unplanned dependency changes during freeze period",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const cmd = ctx.toolInput?.command ?? "";
const isInstall = /^(npm install|yarn add|bun add|pnpm add)\s+\S/.test(cmd);
if (isInstall && process.env.DEPENDENCY_FREEZE === "1") {
return deny("Package installs are frozen. Unset DEPENDENCY_FREEZE to allow.");
}
return allow();
},
});
export { customPolicies };
Örnekler
examples/ dizini hemen çalıştırılabilir ilke dosyaları içerir:
| Dosya | İçerik |
|---|
examples/policies-basic.js | Yaygın ajan başarısızlık modlarını kapsayan beş başlangıç ilkesi |
examples/policies-advanced/index.js | Gelişmiş desenler: geçişli içeri aktarmalar, zaman uyumsuz çağrılar, çıkış temizleme, ve oturum sonu hook’ları |
examples/convention-policies/security-policies.mjs | Kural tabanlı güvenlik ilkeleri (.env yazma bloğu, git geçmişi yeniden yazma engelle) |
examples/convention-policies/workflow-policies.mjs | Kural tabanlı iş akışı ilkeleri (test hatırlatıcıları, denetim dosyası yazmaları) |
Açık dosya örneklerini kullanma
failproofai policies --install --custom ./examples/policies-basic.js
Kural tabanlı örnekleri kullanma
# Proje seviyesine kopyala
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/
# Veya kullanıcı seviyesine kopyala
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
Kurulum komutu gerekmez — dosyalar sonraki hook olayında otomatik olarak alınır.