मुख्य सामग्री पर जाएं
कस्टम पॉलिसीज़ आपको किसी भी एजेंट व्यवहार के लिए नियम लिखने देती हैं: प्रोजेक्ट कन्वेंशन्स को लागू करें, ड्रिफ़्ट को रोकें, विनाशकारी ऑपरेशन्स को गेट करें, स्टक एजेंट्स का पता लगाएं, या Slack, अनुमोदन वर्कफ़्लो और बहुत कुछ के साथ इंटीग्रेट करें। वे built-in पॉलिसीज़ के समान हुक इवेंट सिस्टम और allow, deny, instruct डिसीजन्स का उपयोग करते हैं।

क्विक उदाहरण

// 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();
  },
});
इसे इंस्टॉल करें:
failproofai policies --install --custom ./my-policies.js

कस्टम पॉलिसीज़ लोड करने के दो तरीके

विकल्प 1: कन्वेंशन-आधारित (अनुशंसित)

.failproofai/policies/ में *policies.{js,mjs,ts} फ़ाइलें ड्रॉप करें और वे स्वचालित रूप से लोड हो जाती हैं — कोई फ़्लैग या कॉन्फ़िग परिवर्तन की आवश्यकता नहीं है। यह git hooks की तरह काम करता है: एक फ़ाइल ड्रॉप करें, यह बस काम करता है।
# प्रोजेक्ट स्तर — git में कमिट किया गया, टीम के साथ साझा किया गया
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs

# यूजर स्तर — व्यक्तिगत, सभी प्रोजेक्ट्स पर लागू
~/.failproofai/policies/my-policies.mjs
यह कैसे काम करता है:
  • प्रोजेक्ट और यूजर दोनों डायरेक्टरीज़ को स्कैन किया जाता है (यूनियन — पहला स्कोप-जीत नहीं)
  • फ़ाइलें प्रत्येक डायरेक्टरी के भीतर वर्णक्रम के अनुसार लोड की जाती हैं। क्रम को नियंत्रित करने के लिए 01-, 02- के साथ प्रीफ़िक्स करें
  • केवल *policies.{js,mjs,ts} से मेल खाने वाली फ़ाइलें लोड की जाती हैं; अन्य फ़ाइलों को अनदेखा किया जाता है
  • प्रत्येक फ़ाइल स्वतंत्र रूप से लोड की जाती है (प्रति फ़ाइल fail-open)
  • स्पष्ट --custom और built-in पॉलिसीज़ के साथ काम करता है
कन्वेंशन पॉलिसीज़ एक टीम के साथ पॉलिसीज़ साझा करने का सबसे आसान तरीका हैं। .failproofai/policies/ को git में कमिट करें और हर टीम मेंबर को वे स्वचालित रूप से मिलते हैं।

विकल्प 2: स्पष्ट फ़ाइल पाथ

# कस्टम पॉलिसीज़ फ़ाइल के साथ इंस्टॉल करें
failproofai policies --install --custom ./my-policies.js

# पॉलिसीज़ फ़ाइल पाथ को बदलें
failproofai policies --install --custom ./new-policies.js

# कॉन्फ़िग से कस्टम पॉलिसीज़ पाथ को हटाएं
failproofai policies --uninstall --custom
रिज़ॉल्व किया गया निरपेक्ष पाथ policies-config.json में customPoliciesPath के रूप में संग्रहीत होता है। फ़ाइल हर हुक इवेंट पर ताज़ा लोड की जाती है - इवेंट्स के बीच कोई कैशिंग नहीं होती है।

दोनों को एक साथ उपयोग करना

कन्वेंशन पॉलिसीज़ और स्पष्ट --custom फ़ाइल एक साथ मौजूद हो सकते हैं। लोड ऑर्डर:
  1. स्पष्ट customPoliciesPath फ़ाइल (यदि कॉन्फ़िगर किया गया हो)
  2. प्रोजेक्ट कन्वेंशन फ़ाइलें ({cwd}/.failproofai/policies/, वर्णक्रम)
  3. यूजर कन्वेंशन फ़ाइलें (~/.failproofai/policies/, वर्णक्रम)

API

इंपोर्ट

import { customPolicies, allow, deny, instruct } from "failproofai";

customPolicies.add(hook)

एक पॉलिसी को रजिस्टर करता है। एक ही फ़ाइल में कई पॉलिसीज़ के लिए आवश्यकतानुसार इसे कॉल करें।
customPolicies.add({
  name: string;                         // आवश्यक - अद्वितीय पहचानकर्ता
  description?: string;                 // `failproofai policies` आउटपुट में दिखाया गया
  match?: { events?: HookEventType[] }; // इवेंट प्रकार द्वारा फ़िल्टर करें; सभी से मेल खाने के लिए छोड़ दें
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});

डिसीजन हेल्पर्स

फंक्शनप्रभावकब उपयोग करें
allow()ऑपरेशन को चुप से अनुमति देंकार्रवाई सुरक्षित है, कोई संदेश की आवश्यकता नहीं
deny(message)ऑपरेशन को ब्लॉक करेंएजेंट को यह कार्रवाई नहीं करनी चाहिए
instruct(message)बिना ब्लॉक किए संदर्भ जोड़ेंएजेंट को ट्रैक पर रहने के लिए अतिरिक्त संदर्भ दें
deny(message) - संदेश Claude को "Blocked by failproofai:" के साथ प्रीफ़िक्स किया गया दिखाई देता है। एक एकल deny सभी आगे के मूल्यांकन को शॉर्ट-सर्किट करता है। instruct(message) - संदेश वर्तमान टूल कॉल के लिए Claude के संदर्भ में जोड़ा जाता है। सभी instruct संदेश एकत्रित किए जाते हैं और एक साथ डिलीवर किए जाते हैं।
policyParams में hint फ़ील्ड जोड़कर किसी भी deny या instruct संदेश के लिए अतिरिक्त निर्देश जोड़ सकते हैं — कोई कोड परिवर्तन की आवश्यकता नहीं है। यह कस्टम (custom/), प्रोजेक्ट कन्वेंशन (.failproofai-project/), और यूजर कन्वेंशन (.failproofai-user/) पॉलिसीज़ के लिए भी काम करता है। विवरण के लिए कॉन्फ़िगरेशन → hint देखें।

सूचनात्मक allow संदेश

allow(message) ऑपरेशन को अनुमति देता है और Claude को एक सूचनात्मक संदेश भेजता है। संदेश हुक हैंडलर के stdout प्रतिक्रिया में additionalContext के रूप में डिलीवर किया जाता है — instruct द्वारा उपयोग किया जाने वाला समान तंत्र, लेकिन शब्दार्थ रूप से अलग: यह एक सतर्कता नहीं, एक स्थिति अपडेट है।
फंक्शनप्रभावकब उपयोग करें
allow(message)अनुमति दें और Claude को संदर्भ भेजेंएक जांच पास होने की पुष्टि करें, या बताएं कि जांच को क्यों छोड़ा गया
उपयोग के मामले:
  • स्थिति पुष्टिकरण: allow("All CI checks passed.") — Claude को बताता है कि सब कुछ हरा है
  • Fail-open व्याख्याएं: allow("GitHub CLI not installed, skipping CI check.") — Claude को बताता है कि जांच को क्यों छोड़ा गया ताकि इसके पास पूरा संदर्भ हो
  • कई संदेश जमा होते हैं: यदि कई पॉलिसीज़ प्रत्येक allow(message) रिटर्न करते हैं, तो सभी संदेश नई लाइनों के साथ जुड़ते हैं और एक साथ डिलीवर होते हैं
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.");

    // ... check branch status ...
    if (allPushed) {
      return allow("Branch is up to date with remote.");
    }
    return deny("Unpushed changes detected.");
  },
});

PolicyContext फील्ड्स

फील्डप्रकारविवरण
eventTypestring"PreToolUse", "PostToolUse", "Notification", "Stop"
toolNamestring | undefinedकॉल किया जा रहा टूल (जैसे "Bash", "Write", "Read")
toolInputRecord<string, unknown> | undefinedटूल के इनपुट पैरामीटर्स
payloadRecord<string, unknown>Claude Code से पूर्ण raw इवेंट पेलोड
sessionSessionMetadata | undefinedसेशन संदर्भ (नीचे देखें)

SessionMetadata फील्ड्स

फील्डप्रकारविवरण
sessionIdstringClaude Code सेशन पहचानकर्ता
cwdstringClaude Code सेशन की वर्किंग डायरेक्टरी
transcriptPathstringसेशन की JSONL ट्रांस्क्रिप्ट फ़ाइल का पाथ

इवेंट प्रकार

इवेंटकब फायर होता हैtoolInput सामग्री
PreToolUseClaude एक टूल चलाने से पहलेटूल का इनपुट (जैसे Bash के लिए { command: "..." })
PostToolUseएक टूल पूरा होने के बादटूल का इनपुट + tool_result (आउटपुट)
Notificationजब Claude एक नोटिफिकेशन भेजता है{ message: "...", notification_type: "idle" | "permission_prompt" | ... } - हुक्स को हमेशा allow() रिटर्न करना चाहिए, वे नोटिफिकेशन्स को ब्लॉक नहीं कर सकते
Stopजब Claude सेशन समाप्त होता हैखाली

मूल्यांकन क्रम

पॉलिसीज़ का मूल्यांकन इस क्रम में किया जाता है:
  1. Built-in पॉलिसीज़ (परिभाषा क्रम में)
  2. customPoliciesPath से स्पष्ट कस्टम पॉलिसीज़ (.add() क्रम में)
  3. प्रोजेक्ट .failproofai/policies/ से कन्वेंशन पॉलिसीज़ (फ़ाइलें वर्णक्रम, प्रत्येक के भीतर .add() क्रम)
  4. यूजर ~/.failproofai/policies/ से कन्वेंशन पॉलिसीज़ (फ़ाइलें वर्णक्रम, प्रत्येक के भीतर .add() क्रम)
पहला deny सभी बाद की पॉलिसीज़ को शॉर्ट-सर्किट करता है। सभी instruct संदेश एकत्रित किए जाते हैं और एक साथ डिलीवर किए जाते हैं।

ट्रांसिटिव इंपोर्ट्स

कस्टम पॉलिसी फ़ाइलें रिलेटिव पाथ्स का उपयोग करके स्थानीय मॉड्यूल्स को इंपोर्ट कर सकती हैं:
// 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");
  },
});
एंट्री फ़ाइल से पहुंचने योग्य सभी रिलेटिव इंपोर्ट्स को रिज़ॉल्व किया जाता है। यह from "failproofai" इंपोर्ट्स को वास्तविक dist पाथ में फिर से लिखकर और ESM संगतता सुनिश्चित करने के लिए अस्थायी .mjs फ़ाइलें बनाकर लागू किया जाता है।

इवेंट टाइप फ़िल्टरिंग

match.events का उपयोग करके यह सीमित करें कि कब एक पॉलिसी फायर होती है:
customPolicies.add({
  name: "require-summary-on-stop",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    // केवल तब फायर होता है जब सेशन समाप्त होता है
    // ctx.session.transcriptPath में पूरा सेशन लॉग होता है
    return allow();
  },
});
हर इवेंट प्रकार पर फायर करने के लिए match को पूरी तरह छोड़ दें।

त्रुटि हैंडलिंग और विफलता मोड्स

कस्टम पॉलिसीज़ fail-open हैं: त्रुटियां कभी built-in पॉलिसीज़ को ब्लॉक नहीं करती हैं या हुक हैंडलर को क्रैश नहीं करती हैं।
विफलताव्यवहार
customPoliciesPath सेट नहीं हैकोई स्पष्ट कस्टम पॉलिसीज़ नहीं चलती हैं; कन्वेंशन पॉलिसीज़ और built-ins सामान्य रूप से जारी रहते हैं
फ़ाइल नहीं मिली~/.failproofai/hook.log में चेतावनी लॉग की जाती है; built-ins जारी रहते हैं
सिंटैक्स/इंपोर्ट त्रुटि (स्पष्ट)~/.failproofai/hook.log में त्रुटि लॉग की जाती है; स्पष्ट कस्टम पॉलिसीज़ छोड़ दी जाती हैं
सिंटैक्स/इंपोर्ट त्रुटि (कन्वेंशन)त्रुटि लॉग की जाती है; वह फ़ाइल छोड़ दी जाती है, अन्य कन्वेंशन फ़ाइलें अभी भी लोड होती हैं
fn रनटाइम पर throw करता हैत्रुटि लॉग की जाती है; वह हुक allow के रूप में माना जाता है; अन्य हुक्स जारी रहते हैं
fn 10s से अधिक समय लेता हैटाइमआउट लॉग किया जाता है; allow के रूप में माना जाता है
कन्वेंशन डायरेक्टरी नहीं मिलीकोई कन्वेंशन पॉलिसीज़ नहीं चलती हैं; कोई त्रुटि नहीं
कस्टम पॉलिसी त्रुटियों को डिबग करने के लिए, लॉग फ़ाइल को देखें:
tail -f ~/.failproofai/hook.log

पूरा उदाहरण: कई पॉलिसीज़

// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";

// एजेंट को secrets/ डायरेक्टरी में लिखने से रोकें
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();
  },
});

// एजेंट को ट्रैक पर रखें: कमिट करने से पहले टेस्ट्स सत्यापित करें
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();
  },
});

// फ्रीज़ अवधि के दौरान अनियोजित निर्भरता परिवर्तन को रोकें
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 };

उदाहरण

examples/ डायरेक्टरी में तैयार-से-चलाने योग्य पॉलिसी फ़ाइलें होती हैं:
फ़ाइलसामग्री
examples/policies-basic.jsपांच स्टार्टर पॉलिसीज़ जो सामान्य एजेंट विफलता मोड को कवर करती हैं
examples/policies-advanced/index.jsउन्नत पैटर्न: ट्रांसिटिव इंपोर्ट्स, async कॉल्स, आउटपुट स्क्रबिंग, और सेशन-एंड हुक्स
examples/convention-policies/security-policies.mjsकन्वेंशन-आधारित सुरक्षा पॉलिसीज़ (.env राइट्स को ब्लॉक करें, git इतिहास को फिर से लिखने से रोकें)
examples/convention-policies/workflow-policies.mjsकन्वेंशन-आधारित वर्कफ़्लो पॉलिसीज़ (टेस्ट रिमाइंडर्स, ऑडिट फ़ाइल राइट्स)

स्पष्ट फ़ाइल उदाहरण्स का उपयोग करना

failproofai policies --install --custom ./examples/policies-basic.js

कन्वेंशन-आधारित उदाहरण्स का उपयोग करना

# प्रोजेक्ट स्तर पर कॉपी करें
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/

# या यूजर स्तर पर कॉपी करें
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
कोई इंस्टॉल कमांड की आवश्यकता नहीं है — फ़ाइलें अगली हुक इवेंट पर स्वचालित रूप से लोड हो जाती हैं।