Özel politikalar, herhangi bir agent davranışı için kurallar yazmanıza izin verir: proje kurallarını uygulayın, sapmayı önleyin, yıkıcı işlemleri engelle, sıkışmış aracıları algılayın veya Slack, onay iş akışları ve daha fazlasıyla entegre olun. Yerleşik politikalarla aynı hook etkinliği 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();
},
});
Yükleyin:
failproofai policies --install --custom ./my-policies.js
Özel politikaları yüklemenin iki yolu
Seçenek 1: Kural tabanlı (önerilen)
.failproofai/policies/ dizinine *policies.{js,mjs,ts} dosyalarını bırakın ve otomatik olarak yüklenirler — hiçbir bayrak veya yapılandırma değişikliğine gerek yoktur. Bu git hook’ları gibi çalışır: bir dosya bırakın ve çalışır.
# Proje düzeyi — git'e kaydedilir, ekiple paylaşılır
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs
# Kullanıcı düzeyi — kişisel, tüm projelere uygulanır
~/.failproofai/policies/my-policies.mjs
Nasıl çalışır:
- Hem proje hem de kullanıcı dizinleri taranır (birleşim — ilk-kapsam-kazanır değil)
- Dosyalar her dizin içinde alfabetik olarak yüklenir. Sırayı kontrol etmek için
01-, 02- ile önekleyin
- 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-fail)
- Açık
--custom ve yerleşik politikalarla birlikte çalışır
Kural politikaları, politikaları bir ekip genelinde paylaşmanın en kolay yoludur. .failproofai/policies/ öğesini git’e işleyin ve her takım üyesi otomatik olarak bunları alır.
Seçenek 2: Açık dosya yolu
# Özel politika dosyasıyla yükleyin
failproofai policies --install --custom ./my-policies.js
# Politika dosyasının yolunu değiştirin
failproofai policies --install --custom ./new-policies.js
# Yapılandırmadan özel politika yolunu kaldırın
failproofai policies --uninstall --custom
Çözümlenen mutlak yol, policies-config.json içinde customPoliciesPath olarak depolanır. Dosya her hook etkinliğinde yeniden yüklenir - olaylar arasında önbellekleme yoktur.
Her ikisini birlikte kullanma
Kural politikaları ve açık --custom dosyası birlikte varolabilir. Yükleme sırası:
- Açık
customPoliciesPath dosyası (yapılandırılmışsa)
- Proje kural dosyaları (
{cwd}/.failproofai/policies/, alfabetik)
- Kullanıcı kural dosyaları (
~/.failproofai/policies/, alfabetik)
API
İçe aktarma
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add(hook)
Bir politikayı kaydeder. Aynı dosyada birden çok politika için gerektiği kadar çağırın.
customPolicies.add({
name: string; // zorunlu - benzersiz tanımlayıcı
description?: string; // `failproofai policies` çıktısında gösterilir
match?: { events?: HookEventType[] }; // etkinlik türüne göre filtrele; tümünü eşleştirmek için atlayın
fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});
Karar yardımcıları
| İşlev | Etki | Ne zaman kullanılır |
|---|
allow() | İşleme sessizce izin ver | İşlem güvenli, mesaj gerekmez |
deny(message) | İşlemi engelle | Agent bu işlemi yapmamalı |
instruct(message) | Bloklamadan bağlam ekle | Agent’a yolunda kalması için ekstra bağlam ver |
deny(message) - ileti Claude’a "Blocked by failproofai:" ön eki ile görünür. Tek bir deny tüm diğer değerlendirmeleri kısaltır.
instruct(message) - ileti, Claude’un geçerli araç çağrısı için bağlamına eklenir. Tüm instruct iletileri biriktirilir ve birlikte iletilir.
policyParams içinde hint alanı ekleyerek herhangi bir deny veya instruct iletisine ekstra rehberlik ekleyebilirsiniz — kod değişikliğine gerek yoktur. Bu özel (custom/), proje kural (.failproofai-project/) ve kullanıcı kural (.failproofai-user/) politikaları için de çalışır. Ayrıntılar için Yapılandırma → hint bölümüne bakın.
Bilgilendirici izin iletileri
allow(message) işleme izin verir ve Claude’a bilgilendirici bir ileti gönderir. İleti, hook işleyicisinin stdout yanıtında additionalContext olarak iletilir — instruct tarafından kullanılan mekanizmayla aynı, ancak anlamsal olarak farklı: bir uyarı değil, bir durum güncellemesidir.
| İşlev | Etki | Ne zaman kullanılır |
|---|
allow(message) | İzin ver ve Claude’a bağlam gönder | Bir kontrol geçmesini onaylayın veya bir kontrol 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
- Fail-open açıklamaları:
allow("GitHub CLI not installed, skipping CI check.") — Claude’a bir kontrol neden atlandığını söyler, böylece tam bağlama sahiptir
- Birden çok ileti birikir: birden çok politika
allow(message) döndürürse, tüm iletiler yeni satırlarla birleştirilir ve birlikte iletilir
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.");
// ... branch 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ç (örn. "Bash", "Write", "Read") |
toolInput | Record<string, unknown> | undefined | Aracının giriş parametreleri |
payload | Record<string, unknown> | Claude Code’dan 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 |
Etkinlik türleri
| Etkinlik | Ne zaman ateşlenir | toolInput içeriği |
|---|
PreToolUse | Claude bir aracı çalıştırmadan önce | Aracının girdisi (örn. Bash için { command: "..." }) |
PostToolUse | Bir araç tamamlandıktan sonra | Aracının girdisi + tool_result (çıktı) |
Notification | Claude bir bildirim gönderdiğinde | { message: "...", notification_type: "idle" | "permission_prompt" | ... } - hook’lar her zaman allow() döndürmelidir, bildirimleri bloklamaz |
Stop | Claude oturumu sona erdiğinde | Boş |
Değerlendirme sırası
Politikalar şu sırayla değerlendirilir:
- Yerleşik politikalar (tanım sırasında)
customPoliciesPath öğesinden açık özel politikalar (.add() sırasında)
- Proje
.failproofai/policies/ öğesinden kural politikaları (dosyalar alfabetik, içinde .add() sırası)
- Kullanıcı
~/.failproofai/policies/ öğesinden kural politikaları (dosyalar alfabetik, içinde .add() sırası)
İlk deny tüm sonraki politikaları kısaltır. Tüm instruct iletileri biriktirilir ve birlikte iletilir.
Geçişli içe aktarmalar
Özel politika dosyaları göreli yolları kullanan yerel modülleri içe 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 erişilebilen tüm göreli içe aktarmalar çözülür. Bu, from "failproofai" içe aktarmalarını gerçek dist yoluna yeniden yazarak ve ESM uyumluluğunu sağlamak için geçici .mjs dosyaları oluşturarak uygulanır.
Etkinlik türü filtrelemesi
Bir politikanın ne zaman ateşlendiğini sınırlamak için match.events öğesini kullanın:
customPolicies.add({
name: "require-summary-on-stop",
match: { events: ["Stop"] },
fn: async (ctx) => {
// Yalnızca oturum sona erdiğinde ateşlenir
// ctx.session.transcriptPath tam oturum günlüğünü içerir
return allow();
},
});
Her etkinlik türünde ateşlemek için match öğesini tamamen atlayın.
Hata işleme ve başarısızlık modları
Özel politikalar açık başarısızlık: hatalar hiçbir zaman yerleşik politikaları bloklamaz veya hook işleyicisini çökmez.
| Başarısızlık | Davranış |
|---|
customPoliciesPath ayarlanmadı | Açık özel politika çalışmaz; kural politikaları ve yerleşikler normal şekilde devam eder |
| Dosya bulunamadı | Uyarı ~/.failproofai/hook.log öğesine kaydedilir; yerleşikler devam eder |
| Sözdizimi/içe aktarma hatası (açık) | Hata ~/.failproofai/hook.log öğesine kaydedilir; açık özel politikalar atlanır |
| Sözdizimi/içe aktarma hatası (kural) | Hata kaydedilir; bu dosya atlanır, diğer kural dosyaları yine de yüklenir |
fn çalışma zamanında hatası | Hata kaydedilir; bu hook allow olarak kabul edilir; diğer hook’lar devam eder |
fn 10 saniyeden uzun sürerse | Zaman aşımı kaydedilir; allow olarak kabul edilir |
| Kural dizini eksik | Kural politikası çalışmaz; hata yoktur |
Özel politika hatalarını ayıklamak için günlük dosyasını izleyin:tail -f ~/.failproofai/hook.log
Tam örnek: birden çok politika
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
// Agent'i secrets/ dizinine yazmaktan önle
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();
},
});
// Agent'i yolunda tut: işleme atmadan ö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 plansız 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 çalışmaya hazır politika dosyalarını içerir:
| Dosya | İçerik |
|---|
examples/policies-basic.js | Ortak agent başarısızlık modlarını kapsayan beş başlatıcı politika |
examples/policies-advanced/index.js | Gelişmiş desenleri: geçişli içe aktarmalar, eşzamansız çağrılar, çıktı temizleme ve oturum sonu hook’ları |
examples/convention-policies/security-policies.mjs | Kural tabanlı güvenlik politikaları (.env yazılarını blokla, git geçmişini yeniden yazmayı önle) |
examples/convention-policies/workflow-policies.mjs | Kural tabanlı iş akışı politikaları (test hatırlatmaları, dosya yazma denetimi) |
Açık dosya örneklerini kullanma
failproofai policies --install --custom ./examples/policies-basic.js
Kural tabanlı örnekleri kullanma
# Proje düzeyine kopyala
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/
# Veya kullanıcı düzeyine kopyala
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
Yükleme komutu gerekli değildir — dosyalar sonraki hook etkinliğinde otomatik olarak seçilir.