From 4827625564fa5457f72216ae3a10210e163b76c8 Mon Sep 17 00:00:00 2001 From: NiveditJain Date: Thu, 9 Apr 2026 12:52:05 -0700 Subject: [PATCH 1/5] docs: rename custom-hooks page to custom-policies The docs URL /custom-hooks now serves as /custom-policies to match the product terminology. Updates all cross-references, navigation, page title, and user-facing text. Source code filenames unchanged. Co-Authored-By: Claude Opus 4.6 --- docs/architecture.mdx | 10 ++--- docs/cli/install-policies.mdx | 2 +- docs/cli/list-policies.mdx | 6 +-- docs/cli/remove-policies.mdx | 2 +- docs/configuration.mdx | 4 +- .../{custom-hooks.mdx => custom-policies.mdx} | 38 +++++++++---------- docs/dashboard.mdx | 2 +- docs/docs.json | 2 +- docs/for-agents.mdx | 6 +-- docs/getting-started.mdx | 2 +- docs/introduction.mdx | 2 +- 11 files changed, 38 insertions(+), 38 deletions(-) rename docs/{custom-hooks.mdx => custom-policies.mdx} (87%) diff --git a/docs/architecture.mdx b/docs/architecture.mdx index 10c2b5df..677c46a2 100644 --- a/docs/architecture.mdx +++ b/docs/architecture.mdx @@ -112,8 +112,8 @@ stdin JSON → extract session metadata (session_id, cwd, tool_name, tool_input, etc.) → readMergedHooksConfig(cwd) ← merges project + local + global config → register enabled builtin policies with resolved params - → load custom hooks from customPoliciesPath (if set) - → register custom hooks into policy registry + → load custom policies from customPoliciesPath (if set) + → register custom policies into policy registry → evaluate all policies (builtins first, then custom) → first deny short-circuits → instruct decisions accumulate @@ -193,7 +193,7 @@ Pattern matching inside policies uses parsed command tokens (argv), not raw stri --- -## Custom hooks +## Custom policies `src/hooks/custom-hooks-registry.ts` implements a `globalThis`-backed registry: @@ -208,7 +208,7 @@ export function getCustomHooks(): CustomHook[] { ... } export function clearCustomHooks(): void { ... } // used in tests ``` -`src/hooks/custom-hooks-loader.ts` loads the user's hooks file: +`src/hooks/custom-hooks-loader.ts` loads the user's policy file: 1. Read `customPoliciesPath` from config; skip if absent. 2. Resolve to absolute path; check file exists. @@ -220,7 +220,7 @@ export function clearCustomHooks(): void { ... } // used in tests On any error (file not found, syntax error, import failure), the error is logged to `~/.failproofai/hook.log` and the loader returns an empty array. Built-in policies are unaffected. -Custom hooks are evaluated after all built-in policies. A custom hook `deny` still short-circuits further custom hooks (but all built-ins have already run by that point). +Custom policies are evaluated after all built-in policies. A custom policy `deny` still short-circuits further custom policies (but all built-ins have already run by that point). --- diff --git a/docs/cli/install-policies.mdx b/docs/cli/install-policies.mdx index c70bdb06..0b8cfac8 100644 --- a/docs/cli/install-policies.mdx +++ b/docs/cli/install-policies.mdx @@ -41,7 +41,7 @@ failproofai policies --install block-sudo sanitize-api-keys --scope project # Enable all policies at once failproofai policies --install all -# Install with a custom hooks file +# Install with a custom policies file failproofai policies --install --custom ./my-policies.js ``` diff --git a/docs/cli/list-policies.mdx b/docs/cli/list-policies.mdx index eb3918d2..da66a802 100644 --- a/docs/cli/list-policies.mdx +++ b/docs/cli/list-policies.mdx @@ -1,13 +1,13 @@ --- title: List policies -description: "See which policies are enabled, their parameters, and custom hooks" +description: "See which policies are enabled, their parameters, and custom policies" --- ```bash failproofai policies ``` -Shows all policies with their status, configured parameters, and custom hooks. +Shows all policies with their status, configured parameters, and custom policies. ## Sample output @@ -23,7 +23,7 @@ Failproof AI Hook Policies (user) ✓ sanitize-api-keys Redact API keys from output additionalPatterns: [{ regex: "MY_TOKEN_...", label: "..." }] - ── Custom Hooks (/home/alice/myproject/my-policies.js) ────────────── + ── Custom Policies (/home/alice/myproject/my-policies.js) ────────────── ✓ require-jira-ticket Block commits without ticket ✓ approval-gate Approval gate for destructive ops ``` diff --git a/docs/cli/remove-policies.mdx b/docs/cli/remove-policies.mdx index f78bf517..8d6cabda 100644 --- a/docs/cli/remove-policies.mdx +++ b/docs/cli/remove-policies.mdx @@ -39,6 +39,6 @@ failproofai policies --uninstall block-sudo # Remove hooks from every scope failproofai policies --uninstall --scope all -# Clear custom hooks path +# Clear custom policies path failproofai policies --uninstall --custom ``` diff --git a/docs/configuration.mdx b/docs/configuration.mdx index 2f1014ee..56793dfc 100644 --- a/docs/configuration.mdx +++ b/docs/configuration.mdx @@ -4,7 +4,7 @@ description: "Config file format, three-scope system, and merge rules" icon: gear --- -failproofai uses JSON configuration files to control which policies are active, how they behave, and where custom hooks are loaded from. Configuration is designed to be easy to share with your team - commit it to your repo and every developer gets the same agent safety net. +failproofai uses JSON configuration files to control which policies are active, how they behave, and where custom policies are loaded from. Configuration is designed to be easy to share with your team - commit it to your repo and every developer gets the same agent safety net. --- @@ -122,7 +122,7 @@ Type: `string` (absolute path) Path to a JavaScript file containing custom hook policies. This is set automatically by `failproofai policies --install --custom ` (the path is resolved to absolute before being stored). -The file is loaded fresh on every hook event - there is no caching. See [Custom Hooks](/custom-hooks) for authoring details. +The file is loaded fresh on every hook event - there is no caching. See [Custom Policies](/custom-policies) for authoring details. ### `llm` diff --git a/docs/custom-hooks.mdx b/docs/custom-policies.mdx similarity index 87% rename from docs/custom-hooks.mdx rename to docs/custom-policies.mdx index 51a263bd..4e933551 100644 --- a/docs/custom-hooks.mdx +++ b/docs/custom-policies.mdx @@ -1,10 +1,10 @@ --- -title: Custom Hooks +title: Custom Policies description: "Write your own policies in JavaScript - enforce conventions, prevent drift, detect failures, integrate with external systems" icon: code --- -Custom hooks let you write policies for any agent behavior: enforce project conventions, prevent drift, gate destructive operations, detect stuck agents, or integrate with Slack, approval workflows, and more. They use the same hook event system and `allow`, `deny`, `instruct` decisions as built-in policies. +Custom policies let you write rules for any agent behavior: enforce project conventions, prevent drift, gate destructive operations, detect stuck agents, or integrate with Slack, approval workflows, and more. They use the same hook event system and `allow`, `deny`, `instruct` decisions as built-in policies. --- @@ -40,13 +40,13 @@ failproofai policies --install --custom ./my-policies.js ## Installing and updating ```bash -# Install with a custom hooks file +# Install with a custom policies file failproofai policies --install --custom ./my-policies.js -# Replace the hooks file path +# Replace the policies file path failproofai policies --install --custom ./new-policies.js -# Remove the custom hooks path from config +# Remove the custom policies path from config failproofai policies --uninstall --custom ``` @@ -64,7 +64,7 @@ import { customPolicies, allow, deny, instruct } from "failproofai"; ### `customPolicies.add(hook)` -Registers a hook. Call this as many times as needed for multiple hooks in the same file. +Registers a policy. Call this as many times as needed for multiple policies in the same file. ```ts customPolicies.add({ @@ -118,20 +118,20 @@ customPolicies.add({ ## Evaluation order -Hooks are evaluated in this order: +Policies are evaluated in this order: 1. Built-in policies (in definition order) -2. Custom hooks (in `.add()` order) +2. Custom policies (in `.add()` order) -The first `deny` short-circuits all subsequent hooks. All `instruct` returns accumulate into a single message regardless of which hook produced them. +The first `deny` short-circuits all subsequent policies. All `instruct` returns accumulate into a single message regardless of which policy produced them. --- ## Transitive imports -Custom hook files can import local modules using relative paths: +Custom policy files can import local modules using relative paths: ```js // my-policies.js @@ -152,9 +152,9 @@ All relative imports reachable from the entry file are resolved. This is impleme --- -## Hook event type filtering +## Event type filtering -Use `match.events` to limit when a hook fires: +Use `match.events` to limit when a policy fires: ```js customPolicies.add({ @@ -174,18 +174,18 @@ Omit `match` entirely to fire on every event type. ## Error handling and failure modes -Custom hooks are **fail-open**: errors never block built-in policies or crash the hook handler. +Custom policies are **fail-open**: errors never block built-in policies or crash the hook handler. | Failure | Behavior | |---------|----------| -| `customPoliciesPath` not set | No custom hooks run; built-ins continue normally | +| `customPoliciesPath` not set | No custom policies run; built-ins continue normally | | File not found | Warning logged to `~/.failproofai/hook.log`; built-ins continue | -| Syntax/import error | Error logged to `~/.failproofai/hook.log`; all custom hooks skipped | +| Syntax/import error | Error logged to `~/.failproofai/hook.log`; all custom policies skipped | | `fn` throws at runtime | Error logged; that hook treated as `allow`; other hooks continue | | `fn` takes longer than 10s | Timeout logged; treated as `allow` | -To debug custom hook errors, watch the log file: +To debug custom policy errors, watch the log file: ```bash tail -f ~/.failproofai/hook.log @@ -194,7 +194,7 @@ tail -f ~/.failproofai/hook.log --- -## Full example: multiple hooks +## Full example: multiple policies ```js // my-policies.js @@ -249,9 +249,9 @@ export { customPolicies }; --- -## Examples in the repository +## Examples -The `examples/` directory contains ready-to-run hook files: +The `examples/` directory contains ready-to-run policy files: | File | Contents | |------|----------| diff --git a/docs/dashboard.mdx b/docs/dashboard.mdx index 9da13105..ba982d41 100644 --- a/docs/dashboard.mdx +++ b/docs/dashboard.mdx @@ -66,7 +66,7 @@ A two-tab page for managing policies and reviewing activity. - Toggle individual policies on or off with a single click (writes to `~/.failproofai/policies-config.json`) - Expand a policy to configure its parameters (for policies that support `policyParams`) - Install or remove hooks for a given scope - - Set a custom hooks file path + - Set a custom policies file path - Full paginated history of every hook event that has fired across all sessions diff --git a/docs/docs.json b/docs/docs.json index 5407c330..7aed0739 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -28,7 +28,7 @@ "group": "Core Concepts", "pages": [ "built-in-policies", - "custom-hooks", + "custom-policies", "configuration" ] }, diff --git a/docs/for-agents.mdx b/docs/for-agents.mdx index b2eedc0a..13e0f785 100644 --- a/docs/for-agents.mdx +++ b/docs/for-agents.mdx @@ -16,7 +16,7 @@ npx skills add https://docs.befailproof.ai | Area | What's included | |------|----------------| | Policies | Built-in policy names, event types, parameters, enable/disable | -| Custom hooks | `customPolicies.add()`, match filters, `allow`/`deny`/`instruct` API | +| Custom policies | `customPolicies.add()`, match filters, `allow`/`deny`/`instruct` API | | Context object | `ctx.eventType`, `ctx.toolName`, `ctx.toolInput`, `ctx.session` | | Configuration | `policies-config.json` structure, scope merging, `policyParams` | | CLI | `failproofai policies --install`, `--uninstall`, `--custom`, scopes | @@ -30,8 +30,8 @@ Mintlify generates `llms.txt` from all pages in the navigation. The Failproof AI For targeted context, link directly to a specific page: ```bash -# Just the custom hooks API -npx skills add https://docs.befailproof.ai/custom-hooks +# Just the custom policies API +npx skills add https://docs.befailproof.ai/custom-policies # Just the built-in policies npx skills add https://docs.befailproof.ai/built-in-policies diff --git a/docs/getting-started.mdx b/docs/getting-started.mdx index f365b83b..926c3642 100644 --- a/docs/getting-started.mdx +++ b/docs/getting-started.mdx @@ -123,7 +123,7 @@ Removes hook entries from `~/.claude/settings.json`. Config files in `~/.failpro All 26 policies with parameters - + Write your own policies in JavaScript diff --git a/docs/introduction.mdx b/docs/introduction.mdx index e6cf96a1..f08bd6f2 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -21,7 +21,7 @@ Everything runs locally. No data leaves your machine. Block destructive commands, prevent secret leakage, keep agents inside project boundaries, and more - out of the box. - + Write your own rules in JavaScript with a simple allow / deny / instruct API. From 7507f4fa552a28e4d5201d963d492d6aba8cf9f3 Mon Sep 17 00:00:00 2001 From: NiveditJain Date: Thu, 9 Apr 2026 12:52:14 -0700 Subject: [PATCH 2/5] add Luv dev environment with Docker containers Sets up .luv/ configuration so `luv ` starts two services: - dev-environment: Node 22 + Bun + git + gh + Docker CLI + Claude Code - docs: Mintlify dev server with hot reload on port 3000 Co-Authored-By: Claude Opus 4.6 --- .luv/Dockerfile.dev | 34 ++++++++++++++++++++++++++++++++++ .luv/Dockerfile.docs | 8 ++++++++ .luv/docker-compose.yml | 24 ++++++++++++++++++++++++ .luv/settings.json | 3 +++ 4 files changed, 69 insertions(+) create mode 100644 .luv/Dockerfile.dev create mode 100644 .luv/Dockerfile.docs create mode 100644 .luv/docker-compose.yml create mode 100644 .luv/settings.json diff --git a/.luv/Dockerfile.dev b/.luv/Dockerfile.dev new file mode 100644 index 00000000..b779ba76 --- /dev/null +++ b/.luv/Dockerfile.dev @@ -0,0 +1,34 @@ +FROM node:22-slim + +RUN apt-get update -qq && \ + apt-get install -y -qq --no-install-recommends \ + git curl ca-certificates unzip gnupg && \ + rm -rf /var/lib/apt/lists/* + +# Bun (project requires >= 1.3.0) +RUN curl -fsSL https://bun.sh/install | bash +ENV PATH="/root/.bun/bin:$PATH" + +# gh CLI +RUN install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ + -o /etc/apt/keyrings/githubcli-archive-keyring.gpg && \ + chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ + > /etc/apt/sources.list.d/github-cli.list && \ + apt-get update -qq && apt-get install -y -qq gh && \ + rm -rf /var/lib/apt/lists/* + +# Docker CLI (for the testing protocol in CLAUDE.md) +RUN curl -fsSL https://download.docker.com/linux/debian/gpg \ + -o /etc/apt/keyrings/docker.asc && \ + chmod a+r /etc/apt/keyrings/docker.asc && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" \ + > /etc/apt/sources.list.d/docker.list && \ + apt-get update -qq && apt-get install -y -qq docker-ce-cli && \ + rm -rf /var/lib/apt/lists/* + +# Claude Code +RUN npm install -g @anthropic-ai/claude-code + +WORKDIR /workspace diff --git a/.luv/Dockerfile.docs b/.luv/Dockerfile.docs new file mode 100644 index 00000000..263753d6 --- /dev/null +++ b/.luv/Dockerfile.docs @@ -0,0 +1,8 @@ +FROM node:22-slim + +RUN npm install -g mintlify + +WORKDIR /app/docs +EXPOSE 3000 + +CMD ["mintlify", "dev", "--host", "0.0.0.0"] diff --git a/.luv/docker-compose.yml b/.luv/docker-compose.yml new file mode 100644 index 00000000..8fe32bfa --- /dev/null +++ b/.luv/docker-compose.yml @@ -0,0 +1,24 @@ +services: + dev-environment: + build: + context: .luv + dockerfile: Dockerfile.dev + volumes: + - .:/workspace + - /var/run/docker.sock:/var/run/docker.sock + working_dir: /workspace + stdin_open: true + tty: true + network_mode: host + environment: + - FAILPROOFAI_TELEMETRY_DISABLED=1 + + docs: + build: + context: .luv + dockerfile: Dockerfile.docs + volumes: + - ./docs:/app/docs + ports: + - "3000:3000" + restart: unless-stopped diff --git a/.luv/settings.json b/.luv/settings.json new file mode 100644 index 00000000..75f9c995 --- /dev/null +++ b/.luv/settings.json @@ -0,0 +1,3 @@ +{ + "compose_file": ".luv/docker-compose.yml" +} From 82cf0eabbb8d34b41991d09ff65fea32ea8d0256 Mon Sep 17 00:00:00 2001 From: NiveditJain Date: Thu, 9 Apr 2026 13:13:18 -0700 Subject: [PATCH 3/5] revert Luv setup, update Dockerfile for docs hot reload Removes .luv/ configuration (will be added later). Updates the root Dockerfile to support volume-mounted docs with hot reload instead of baking content in at build time. Usage: docker run -v ./docs:/app/docs -p 3000:3000 Co-Authored-By: Claude Opus 4.6 --- .luv/Dockerfile.dev | 34 ---------------------------------- .luv/Dockerfile.docs | 8 -------- .luv/docker-compose.yml | 24 ------------------------ .luv/settings.json | 3 --- Dockerfile | 5 +---- 5 files changed, 1 insertion(+), 73 deletions(-) delete mode 100644 .luv/Dockerfile.dev delete mode 100644 .luv/Dockerfile.docs delete mode 100644 .luv/docker-compose.yml delete mode 100644 .luv/settings.json diff --git a/.luv/Dockerfile.dev b/.luv/Dockerfile.dev deleted file mode 100644 index b779ba76..00000000 --- a/.luv/Dockerfile.dev +++ /dev/null @@ -1,34 +0,0 @@ -FROM node:22-slim - -RUN apt-get update -qq && \ - apt-get install -y -qq --no-install-recommends \ - git curl ca-certificates unzip gnupg && \ - rm -rf /var/lib/apt/lists/* - -# Bun (project requires >= 1.3.0) -RUN curl -fsSL https://bun.sh/install | bash -ENV PATH="/root/.bun/bin:$PATH" - -# gh CLI -RUN install -m 0755 -d /etc/apt/keyrings && \ - curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ - -o /etc/apt/keyrings/githubcli-archive-keyring.gpg && \ - chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && \ - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ - > /etc/apt/sources.list.d/github-cli.list && \ - apt-get update -qq && apt-get install -y -qq gh && \ - rm -rf /var/lib/apt/lists/* - -# Docker CLI (for the testing protocol in CLAUDE.md) -RUN curl -fsSL https://download.docker.com/linux/debian/gpg \ - -o /etc/apt/keyrings/docker.asc && \ - chmod a+r /etc/apt/keyrings/docker.asc && \ - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian bookworm stable" \ - > /etc/apt/sources.list.d/docker.list && \ - apt-get update -qq && apt-get install -y -qq docker-ce-cli && \ - rm -rf /var/lib/apt/lists/* - -# Claude Code -RUN npm install -g @anthropic-ai/claude-code - -WORKDIR /workspace diff --git a/.luv/Dockerfile.docs b/.luv/Dockerfile.docs deleted file mode 100644 index 263753d6..00000000 --- a/.luv/Dockerfile.docs +++ /dev/null @@ -1,8 +0,0 @@ -FROM node:22-slim - -RUN npm install -g mintlify - -WORKDIR /app/docs -EXPOSE 3000 - -CMD ["mintlify", "dev", "--host", "0.0.0.0"] diff --git a/.luv/docker-compose.yml b/.luv/docker-compose.yml deleted file mode 100644 index 8fe32bfa..00000000 --- a/.luv/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - dev-environment: - build: - context: .luv - dockerfile: Dockerfile.dev - volumes: - - .:/workspace - - /var/run/docker.sock:/var/run/docker.sock - working_dir: /workspace - stdin_open: true - tty: true - network_mode: host - environment: - - FAILPROOFAI_TELEMETRY_DISABLED=1 - - docs: - build: - context: .luv - dockerfile: Dockerfile.docs - volumes: - - ./docs:/app/docs - ports: - - "3000:3000" - restart: unless-stopped diff --git a/.luv/settings.json b/.luv/settings.json deleted file mode 100644 index 75f9c995..00000000 --- a/.luv/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "compose_file": ".luv/docker-compose.yml" -} diff --git a/Dockerfile b/Dockerfile index 6a2f1c5f..263753d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,8 @@ FROM node:22-slim -WORKDIR /app - RUN npm install -g mintlify -COPY docs/ ./ - +WORKDIR /app/docs EXPOSE 3000 CMD ["mintlify", "dev", "--host", "0.0.0.0"] From 4909b6e2ef5c69c9386c11e2f739842aad69c6bf Mon Sep 17 00:00:00 2001 From: NiveditJain Date: Thu, 9 Apr 2026 13:17:17 -0700 Subject: [PATCH 4/5] rename Dockerfile to Dockerfile.docs, remove docs/Dockerfile Clearer naming for the docs dev server image. Removes the duplicate Dockerfile inside docs/ since the root one is the canonical version. Co-Authored-By: Claude Opus 4.6 --- Dockerfile => Dockerfile.docs | 0 docs/Dockerfile | 11 ----------- 2 files changed, 11 deletions(-) rename Dockerfile => Dockerfile.docs (100%) delete mode 100644 docs/Dockerfile diff --git a/Dockerfile b/Dockerfile.docs similarity index 100% rename from Dockerfile rename to Dockerfile.docs diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index 6a2f1c5f..00000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM node:22-slim - -WORKDIR /app - -RUN npm install -g mintlify - -COPY docs/ ./ - -EXPOSE 3000 - -CMD ["mintlify", "dev", "--host", "0.0.0.0"] From 586b1ba3251b214aa8880e5f182571ab0f3bff53 Mon Sep 17 00:00:00 2001 From: NiveditJain Date: Thu, 9 Apr 2026 13:18:55 -0700 Subject: [PATCH 5/5] Dockerfile.docs: add non-root user, restore COPY for standalone use Addresses CodeRabbit review: - Run as non-root user (docsuser, UID 10001) for security - COPY docs/ into image so it works without a bind mount - Bind mount (-v ./docs:/app/docs) still overrides for hot reload Co-Authored-By: Claude Opus 4.6 --- Dockerfile.docs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile.docs b/Dockerfile.docs index 263753d6..b8db06d6 100644 --- a/Dockerfile.docs +++ b/Dockerfile.docs @@ -2,7 +2,11 @@ FROM node:22-slim RUN npm install -g mintlify +RUN useradd --create-home --uid 10001 docsuser WORKDIR /app/docs +COPY --chown=docsuser:docsuser docs/ ./ + +USER docsuser EXPOSE 3000 CMD ["mintlify", "dev", "--host", "0.0.0.0"]