failproofai 0.0.2-beta.1 → 0.0.2-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +17 -17
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +17 -17
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +16 -16
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -16
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__02nt~6d._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0a3kr67._.js → [root-of-the-server]__07k6eu-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rbuarm._.js → [root-of-the-server]__0kfv9fw._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0osi8nq._.js → [root-of-the-server]__0okos0k._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +5 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0rd0oc-._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/{0a08gn8709y98.js → 0.jo.465b6_k..js} +1 -1
- package/.next/standalone/.next/static/chunks/{0jhw8ofx.5g_e.js → 01haq0a3zrx0v.js} +1 -1
- package/.next/standalone/.next/static/chunks/08f78tecvx61l.css +1 -0
- package/.next/standalone/.next/static/chunks/{0mr-jhx402yci.js → 0a6xi1a8f_qlp.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0qvj8bhl661lq.js → 0mq7ze1vkeo1p.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0gcz-jqgqz~9m.js → 0p_fpyfmmohnx.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0kob_5.phc~sk.js → 0qwyj3m400l_g.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0mjc3aq2wxvlt.js → 0t94r_mk0s7e4.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0q7z97izctgrw.js → 139~00zc9.u7s.js} +1 -1
- package/.next/standalone/Dockerfile.docs +12 -0
- package/.next/standalone/README.md +68 -55
- package/.next/standalone/bin/failproofai.mjs +221 -128
- package/.next/standalone/dist/cli.mjs +415 -106
- package/.next/standalone/dist/index.js +2 -2
- package/.next/standalone/docs/{architecture.md → architecture.mdx} +40 -23
- package/.next/standalone/docs/{built-in-policies.md → built-in-policies.mdx} +134 -12
- package/.next/standalone/docs/cli/dashboard.mdx +28 -0
- package/.next/standalone/docs/cli/environment-variables.mdx +34 -0
- package/.next/standalone/docs/cli/hook.mdx +30 -0
- package/.next/standalone/docs/cli/install-policies.mdx +48 -0
- package/.next/standalone/docs/cli/list-policies.mdx +31 -0
- package/.next/standalone/docs/cli/remove-policies.mdx +44 -0
- package/.next/standalone/docs/cli/version.mdx +12 -0
- package/.next/standalone/docs/{configuration.md → configuration.mdx} +16 -16
- package/.next/standalone/docs/{custom-hooks.md → custom-policies.mdx} +80 -42
- package/.next/standalone/docs/{dashboard.md → dashboard.mdx} +26 -29
- package/.next/standalone/docs/docs.json +31 -4
- package/.next/standalone/docs/examples.mdx +253 -0
- package/.next/standalone/docs/for-agents.mdx +38 -0
- package/.next/standalone/docs/getting-started.mdx +134 -0
- package/.next/standalone/docs/introduction.mdx +57 -0
- package/.next/standalone/docs/logo/dark.svg +21 -0
- package/.next/standalone/docs/logo/light.svg +21 -0
- package/.next/standalone/docs/{package-aliases.md → package-aliases.mdx} +5 -5
- package/.next/standalone/docs/{testing.md → testing.mdx} +11 -11
- package/.next/standalone/package.json +6 -9
- package/.next/standalone/scripts/publish-aliases.mjs +4 -2
- package/.next/standalone/skills-lock.json +10 -0
- package/.next/standalone/src/cli-error.ts +18 -0
- package/.next/standalone/src/hooks/builtin-policies.ts +259 -20
- package/.next/standalone/src/hooks/manager.ts +17 -3
- package/.next/standalone/src/hooks/policy-evaluator.ts +19 -1
- package/.next/standalone/src/hooks/policy-helpers.ts +2 -2
- package/.next/standalone/vitest.config.e2e.mts +3 -0
- package/.next/standalone/vitest.config.mts +3 -0
- package/README.md +68 -55
- package/bin/failproofai.mjs +221 -128
- package/dist/cli.mjs +415 -106
- package/dist/index.js +2 -2
- package/package.json +6 -9
- package/scripts/publish-aliases.mjs +4 -2
- package/src/cli-error.ts +18 -0
- package/src/hooks/builtin-policies.ts +259 -20
- package/src/hooks/manager.ts +17 -3
- package/src/hooks/policy-evaluator.ts +19 -1
- package/src/hooks/policy-helpers.ts +2 -2
- package/.next/standalone/.next/static/chunks/15jpradyu_531.css +0 -1
- package/.next/standalone/docs/cli-reference.md +0 -175
- package/.next/standalone/docs/getting-started.md +0 -128
- package/.next/standalone/docs/introduction.md +0 -47
- /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_ssgManifest.js +0 -0
|
@@ -4,7 +4,7 @@ description: "How the hook handler, config loading, and policy evaluation work i
|
|
|
4
4
|
icon: sitemap
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
This document explains how failproofai works internally: how the hook system
|
|
7
|
+
This document explains how failproofai works internally: how the hook system intercepts agent tool calls, how configuration is loaded and merged, how policies are evaluated, and how the dashboard monitors agent activity.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -12,8 +12,8 @@ This document explains how failproofai works internally: how the hook system pro
|
|
|
12
12
|
|
|
13
13
|
failproofai has two independent subsystems:
|
|
14
14
|
|
|
15
|
-
1. **Hook handler**
|
|
16
|
-
2. **Dashboard**
|
|
15
|
+
1. **Hook handler** - A fast CLI subprocess that Claude Code invokes on every agent tool call. Evaluates policies and returns a decision.
|
|
16
|
+
2. **Agent Monitor (Dashboard)** - A Next.js web application for monitoring agent sessions and managing policies.
|
|
17
17
|
|
|
18
18
|
Both subsystems share configuration files in `~/.failproofai/` and the project's `.failproofai/` directory, but they run as separate processes and communicate only through the filesystem.
|
|
19
19
|
|
|
@@ -23,7 +23,7 @@ Both subsystems share configuration files in `~/.failproofai/` and the project's
|
|
|
23
23
|
|
|
24
24
|
### Integration with Claude Code
|
|
25
25
|
|
|
26
|
-
When you run `failproofai --install
|
|
26
|
+
When you run `failproofai policies --install`, it writes entries like this into `~/.claude/settings.json`:
|
|
27
27
|
|
|
28
28
|
```json
|
|
29
29
|
{
|
|
@@ -60,7 +60,7 @@ Claude Code then invokes `failproofai --hook PreToolUse` as a subprocess before
|
|
|
60
60
|
}
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
For `PostToolUse` events, the payload
|
|
63
|
+
For `PostToolUse` events, the payload also contains `tool_result` with the tool's output.
|
|
64
64
|
|
|
65
65
|
The handler enforces a 1 MB stdin limit. Payloads exceeding this are discarded and all policies implicitly allow.
|
|
66
66
|
|
|
@@ -102,21 +102,38 @@ The handler enforces a 1 MB stdin limit. Payloads exceeding this are discarded a
|
|
|
102
102
|
- Exit code: `0`
|
|
103
103
|
- Empty stdout
|
|
104
104
|
|
|
105
|
+
**Allow with message (beta):**
|
|
106
|
+
|
|
107
|
+
Since v0.0.2-beta.3, `allow(message)` lets a policy send informational context back to Claude even when the operation is permitted. The hook handler writes the following JSON to **stdout** (not a config file — this is the handler's response to Claude Code, just like deny and instruct responses above):
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
// Written to stdout by the hook handler process
|
|
111
|
+
{
|
|
112
|
+
"hookSpecificOutput": {
|
|
113
|
+
"additionalContext": "All CI checks passed on branch 'feat/my-feature'."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
- Exit code: `0` (operation is allowed)
|
|
118
|
+
- When multiple policies return `allow` with a message, their messages are joined with newlines into a single `additionalContext` string
|
|
119
|
+
- If no policy provides a message, stdout is empty (same as before)
|
|
120
|
+
|
|
105
121
|
### Processing pipeline
|
|
106
122
|
|
|
107
123
|
`src/hooks/handler.ts` implements the full pipeline:
|
|
108
124
|
|
|
109
|
-
```
|
|
125
|
+
```text
|
|
110
126
|
stdin JSON
|
|
111
127
|
→ parse payload (max 1 MB)
|
|
112
128
|
→ extract session metadata (session_id, cwd, tool_name, tool_input, etc.)
|
|
113
129
|
→ readMergedHooksConfig(cwd) ← merges project + local + global config
|
|
114
130
|
→ register enabled builtin policies with resolved params
|
|
115
|
-
→ load custom
|
|
116
|
-
→ register custom
|
|
131
|
+
→ load custom policies from customPoliciesPath (if set)
|
|
132
|
+
→ register custom policies into policy registry
|
|
117
133
|
→ evaluate all policies (builtins first, then custom)
|
|
118
134
|
→ first deny short-circuits
|
|
119
135
|
→ instruct decisions accumulate
|
|
136
|
+
→ allow messages accumulate
|
|
120
137
|
→ write JSON decision to stdout
|
|
121
138
|
→ persist event to ~/.failproofai/hook-activity.jsonl
|
|
122
139
|
→ exit
|
|
@@ -130,17 +147,17 @@ The entire process runs in under 100ms for typical payloads with no LLM calls.
|
|
|
130
147
|
|
|
131
148
|
`src/hooks/hooks-config.ts` implements three-scope config loading.
|
|
132
149
|
|
|
133
|
-
```
|
|
150
|
+
```text
|
|
134
151
|
[1] {cwd}/.failproofai/policies-config.json ← project (highest priority)
|
|
135
152
|
[2] {cwd}/.failproofai/policies-config.local.json ← local
|
|
136
153
|
[3] ~/.failproofai/policies-config.json ← global (lowest priority)
|
|
137
154
|
```
|
|
138
155
|
|
|
139
156
|
Merge logic:
|
|
140
|
-
- `enabledPolicies`
|
|
141
|
-
- `policyParams`
|
|
142
|
-
- `customPoliciesPath`
|
|
143
|
-
- `llm`
|
|
157
|
+
- `enabledPolicies` - deduplicated union across all three files
|
|
158
|
+
- `policyParams` - per-policy key, first file that defines it wins entirely
|
|
159
|
+
- `customPoliciesPath` - first file that defines it wins
|
|
160
|
+
- `llm` - first file that defines it wins
|
|
144
161
|
|
|
145
162
|
The web dashboard uses `readHooksConfig()` (global only) for reading and writing, since it is not invoked with a project cwd.
|
|
146
163
|
|
|
@@ -169,7 +186,7 @@ After all policies run:
|
|
|
169
186
|
|
|
170
187
|
## Builtin policies
|
|
171
188
|
|
|
172
|
-
`src/hooks/builtin-policies.ts` defines all
|
|
189
|
+
`src/hooks/builtin-policies.ts` defines all 26 built-in policies as `BuiltinPolicyDefinition` objects:
|
|
173
190
|
|
|
174
191
|
```typescript
|
|
175
192
|
interface BuiltinPolicyDefinition {
|
|
@@ -193,7 +210,7 @@ Pattern matching inside policies uses parsed command tokens (argv), not raw stri
|
|
|
193
210
|
|
|
194
211
|
---
|
|
195
212
|
|
|
196
|
-
## Custom
|
|
213
|
+
## Custom policies
|
|
197
214
|
|
|
198
215
|
`src/hooks/custom-hooks-registry.ts` implements a `globalThis`-backed registry:
|
|
199
216
|
|
|
@@ -208,7 +225,7 @@ export function getCustomHooks(): CustomHook[] { ... }
|
|
|
208
225
|
export function clearCustomHooks(): void { ... } // used in tests
|
|
209
226
|
```
|
|
210
227
|
|
|
211
|
-
`src/hooks/custom-hooks-loader.ts` loads the user's
|
|
228
|
+
`src/hooks/custom-hooks-loader.ts` loads the user's policy file:
|
|
212
229
|
|
|
213
230
|
1. Read `customPoliciesPath` from config; skip if absent.
|
|
214
231
|
2. Resolve to absolute path; check file exists.
|
|
@@ -220,7 +237,7 @@ export function clearCustomHooks(): void { ... } // used in tests
|
|
|
220
237
|
|
|
221
238
|
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.
|
|
222
239
|
|
|
223
|
-
Custom
|
|
240
|
+
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).
|
|
224
241
|
|
|
225
242
|
---
|
|
226
243
|
|
|
@@ -249,7 +266,7 @@ One line per policy that made a non-allow decision. Allow decisions are not logg
|
|
|
249
266
|
|
|
250
267
|
The dashboard is a **Next.js 16** application using the App Router with React Server Components and Server Actions.
|
|
251
268
|
|
|
252
|
-
```
|
|
269
|
+
```text
|
|
253
270
|
app/
|
|
254
271
|
layout.tsx ← Root layout (theme, telemetry, nav)
|
|
255
272
|
projects/page.tsx ← Server component: list all Claude projects
|
|
@@ -275,22 +292,22 @@ app/
|
|
|
275
292
|
|
|
276
293
|
**Key design decisions:**
|
|
277
294
|
|
|
278
|
-
- No database
|
|
279
|
-
- Server Actions for mutations
|
|
280
|
-
- React Server Components for read pages
|
|
295
|
+
- No database - all persistent state is in plain files (`~/.failproofai/`, `~/.claude/projects/`).
|
|
296
|
+
- Server Actions for mutations - no REST API needed for CRUD operations.
|
|
297
|
+
- React Server Components for read pages - faster initial load, no client bundle for data fetching.
|
|
281
298
|
- Client components only where interactivity is needed (policy toggles, activity search, log viewer).
|
|
282
299
|
|
|
283
300
|
---
|
|
284
301
|
|
|
285
302
|
## File layout
|
|
286
303
|
|
|
287
|
-
```
|
|
304
|
+
```text
|
|
288
305
|
failproofai/
|
|
289
306
|
├── bin/
|
|
290
307
|
│ └── failproofai.mjs # CLI router (hook / dashboard / install / etc.)
|
|
291
308
|
├── src/hooks/
|
|
292
309
|
│ ├── handler.ts # Hook event pipeline
|
|
293
|
-
│ ├── builtin-policies.ts #
|
|
310
|
+
│ ├── builtin-policies.ts # 26 policy definitions
|
|
294
311
|
│ ├── policy-evaluator.ts # Policy execution engine
|
|
295
312
|
│ ├── policy-registry.ts # Policy registration and lookup
|
|
296
313
|
│ ├── policy-types.ts # TypeScript interfaces
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Built-in Policies
|
|
3
|
-
description: "All
|
|
3
|
+
description: "All 30 built-in policies that catch common agent failure modes"
|
|
4
4
|
icon: shield
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
failproofai ships with
|
|
7
|
+
failproofai ships with 30 built-in policies that catch common agent failure modes. Each policy fires on a specific hook event type and tool name. Nine policies accept parameters that let you tune their behavior without writing code. Four beta workflow policies enforce a commit → push → PR → CI pipeline before Claude stops.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -21,13 +21,19 @@ Policies are grouped into categories:
|
|
|
21
21
|
| [Git](#git) | block-push-master, block-work-on-main, block-force-push, warn-git-amend, warn-git-stash-drop, warn-all-files-staged | PreToolUse |
|
|
22
22
|
| [Database](#database) | warn-destructive-sql, warn-schema-alteration | PreToolUse |
|
|
23
23
|
| [Warnings](#warnings) | warn-large-file-write, warn-package-publish, warn-background-process, warn-global-package-install | PreToolUse |
|
|
24
|
+
| [Workflow (beta)](#workflow-beta) | require-commit-before-stop, require-push-before-stop, require-pr-before-stop, require-ci-green-before-stop | Stop |
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
- **`block-`** — stop the agent from proceeding.
|
|
27
|
+
- **`warn-`** — give the agent additional context so it can self-correct.
|
|
28
|
+
- **`sanitize-`** — scrub sensitive data from tool output before the agent sees it.
|
|
29
|
+
- **`require-`** — block the Stop event until conditions are met.
|
|
26
30
|
|
|
27
31
|
---
|
|
28
32
|
|
|
29
33
|
## Dangerous commands
|
|
30
34
|
|
|
35
|
+
Prevent agents from running operations that are hard to undo or that could damage the host system.
|
|
36
|
+
|
|
31
37
|
### `block-sudo`
|
|
32
38
|
|
|
33
39
|
**Event:** PreToolUse (Bash)
|
|
@@ -55,7 +61,9 @@ Blocks invocations that include the `sudo` keyword. Pattern matching is done on
|
|
|
55
61
|
|
|
56
62
|
With this config, `sudo systemctl status nginx` is allowed, but `sudo rm /etc/hosts` is denied.
|
|
57
63
|
|
|
58
|
-
>
|
|
64
|
+
<Note>
|
|
65
|
+
Patterns are matched against parsed tokens, not the raw command string. This prevents bypass via appended shell operators (e.g. `sudo systemctl status x; rm -rf /` does not match `sudo systemctl status *`).
|
|
66
|
+
</Note>
|
|
59
67
|
|
|
60
68
|
---
|
|
61
69
|
|
|
@@ -96,7 +104,7 @@ No parameters.
|
|
|
96
104
|
### `block-failproofai-commands`
|
|
97
105
|
|
|
98
106
|
**Event:** PreToolUse (Bash)
|
|
99
|
-
**Default:** Denies commands that would uninstall or disable failproofai itself (e.g. `npm uninstall failproofai`, `failproofai --
|
|
107
|
+
**Default:** Denies commands that would uninstall or disable failproofai itself (e.g. `npm uninstall failproofai`, `failproofai policies --uninstall`).
|
|
100
108
|
|
|
101
109
|
No parameters.
|
|
102
110
|
|
|
@@ -104,7 +112,7 @@ No parameters.
|
|
|
104
112
|
|
|
105
113
|
## Secrets (sanitizers)
|
|
106
114
|
|
|
107
|
-
Sanitizer policies fire on **PostToolUse** events. When Claude runs a Bash command, reads a file, or calls any tool, these policies inspect the output before it is returned to Claude. If a secret pattern is detected, the policy returns a deny decision that prevents the output from being passed back.
|
|
115
|
+
Stop agents from leaking credentials into their context or output. Sanitizer policies fire on **PostToolUse** events. When Claude runs a Bash command, reads a file, or calls any tool, these policies inspect the output before it is returned to Claude. If a secret pattern is detected, the policy returns a deny decision that prevents the output from being passed back.
|
|
108
116
|
|
|
109
117
|
### `sanitize-jwt`
|
|
110
118
|
|
|
@@ -172,12 +180,14 @@ No parameters.
|
|
|
172
180
|
|
|
173
181
|
## Environment
|
|
174
182
|
|
|
183
|
+
Protect sensitive environment configuration from being read or exposed by agents.
|
|
184
|
+
|
|
175
185
|
### `block-env-files`
|
|
176
186
|
|
|
177
187
|
**Event:** PreToolUse (Bash, Read)
|
|
178
188
|
**Default:** Denies reading `.env` files via `cat .env`, `Read` tool calls with `.env` as the file path, etc.
|
|
179
189
|
|
|
180
|
-
Does not block `.envrc` or other environment-adjacent files
|
|
190
|
+
Does not block `.envrc` or other environment-adjacent files - only files named exactly `.env`.
|
|
181
191
|
|
|
182
192
|
No parameters.
|
|
183
193
|
|
|
@@ -194,6 +204,8 @@ No parameters.
|
|
|
194
204
|
|
|
195
205
|
## File access
|
|
196
206
|
|
|
207
|
+
Keep agents working inside project boundaries and away from sensitive files.
|
|
208
|
+
|
|
197
209
|
### `block-read-outside-cwd`
|
|
198
210
|
|
|
199
211
|
**Event:** PreToolUse (Read, Bash)
|
|
@@ -246,6 +258,8 @@ No parameters.
|
|
|
246
258
|
|
|
247
259
|
## Git
|
|
248
260
|
|
|
261
|
+
Prevent accidental pushes, force-pushes, and branch mistakes that are hard to undo.
|
|
262
|
+
|
|
249
263
|
### `block-push-master`
|
|
250
264
|
|
|
251
265
|
**Event:** PreToolUse (Bash)
|
|
@@ -269,7 +283,9 @@ No parameters.
|
|
|
269
283
|
}
|
|
270
284
|
```
|
|
271
285
|
|
|
272
|
-
>
|
|
286
|
+
<Tip>
|
|
287
|
+
To allow pushing to all branches (effectively disabling this policy without removing it from `enabledPolicies`), set `protectedBranches: []`.
|
|
288
|
+
</Tip>
|
|
273
289
|
|
|
274
290
|
---
|
|
275
291
|
|
|
@@ -324,6 +340,8 @@ No parameters.
|
|
|
324
340
|
|
|
325
341
|
## Database
|
|
326
342
|
|
|
343
|
+
Catch destructive SQL operations before they execute against your database.
|
|
344
|
+
|
|
327
345
|
### `warn-destructive-sql`
|
|
328
346
|
|
|
329
347
|
**Event:** PreToolUse (Bash)
|
|
@@ -344,6 +362,8 @@ No parameters.
|
|
|
344
362
|
|
|
345
363
|
## Warnings
|
|
346
364
|
|
|
365
|
+
Give agents extra context before potentially risky but non-destructive operations.
|
|
366
|
+
|
|
347
367
|
### `warn-large-file-write`
|
|
348
368
|
|
|
349
369
|
**Event:** PreToolUse (Write)
|
|
@@ -367,7 +387,9 @@ No parameters.
|
|
|
367
387
|
}
|
|
368
388
|
```
|
|
369
389
|
|
|
370
|
-
>
|
|
390
|
+
<Note>
|
|
391
|
+
The hook handler enforces a 1 MB stdin limit on payloads. To test this policy with small content, set `thresholdKb` to a value well below 1024.
|
|
392
|
+
</Note>
|
|
371
393
|
|
|
372
394
|
---
|
|
373
395
|
|
|
@@ -398,15 +420,115 @@ No parameters.
|
|
|
398
420
|
|
|
399
421
|
---
|
|
400
422
|
|
|
423
|
+
## AI behavior
|
|
424
|
+
|
|
425
|
+
Detect when agents get stuck or behave unexpectedly.
|
|
426
|
+
|
|
427
|
+
### `warn-repeated-tool-calls`
|
|
428
|
+
|
|
429
|
+
**Event:** PreToolUse (all tools)
|
|
430
|
+
**Default:** Instructs Claude to reconsider when the same tool is called 3+ times with identical parameters - a common sign the agent is stuck in a loop.
|
|
431
|
+
|
|
432
|
+
No parameters.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Workflow (beta)
|
|
437
|
+
|
|
438
|
+
Enforce a disciplined end-of-session workflow. These policies fire on the **Stop** event and deny Claude from stopping until each condition is met. They follow a natural dependency chain: commit → push → PR → CI. If a policy denies, later policies in the chain are skipped (deny short-circuits).
|
|
439
|
+
|
|
440
|
+
All workflow policies are **fail-open**: if the required tool is not available (e.g. `gh` not installed, no git remote), the policy allows with an informational message explaining why the check was skipped.
|
|
441
|
+
|
|
442
|
+
### `require-commit-before-stop`
|
|
443
|
+
|
|
444
|
+
**Event:** Stop
|
|
445
|
+
**Default:** Denies stopping when there are uncommitted changes (modified, staged, or untracked files). Returns an informational message when the working directory is clean.
|
|
446
|
+
|
|
447
|
+
No parameters.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
### `require-push-before-stop`
|
|
452
|
+
|
|
453
|
+
**Event:** Stop
|
|
454
|
+
**Default:** Denies stopping when there are unpushed commits or when the current branch has no remote tracking branch. Suggests `git push -u` to create a tracking branch if needed. Fails open if no remote is configured.
|
|
455
|
+
|
|
456
|
+
**Parameters:**
|
|
457
|
+
|
|
458
|
+
| Param | Type | Default | Description |
|
|
459
|
+
|-------|------|---------|-------------|
|
|
460
|
+
| `remote` | `string` | `"origin"` | Remote name to push to. |
|
|
461
|
+
|
|
462
|
+
**Example:**
|
|
463
|
+
|
|
464
|
+
```json
|
|
465
|
+
{
|
|
466
|
+
"policyParams": {
|
|
467
|
+
"require-push-before-stop": {
|
|
468
|
+
"remote": "upstream"
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
### `require-pr-before-stop`
|
|
477
|
+
|
|
478
|
+
**Event:** Stop
|
|
479
|
+
**Default:** Denies stopping when no pull request exists for the current branch, or when the existing PR is closed/merged. Instructs Claude to create a PR with `gh pr create`.
|
|
480
|
+
|
|
481
|
+
No parameters.
|
|
482
|
+
|
|
483
|
+
<Note>
|
|
484
|
+
This policy requires [GitHub CLI](https://cli.github.com/) (`gh`) to be installed and authenticated.
|
|
485
|
+
Run `gh auth login` with a personal access token that has `repo` scope for read access to
|
|
486
|
+
pull requests. If `gh` is not installed or not authenticated, the policy fails open and reports the reason to Claude.
|
|
487
|
+
</Note>
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### `require-ci-green-before-stop`
|
|
492
|
+
|
|
493
|
+
**Event:** Stop
|
|
494
|
+
**Default:** Denies stopping when CI checks are failing or still running on the current branch. Treats `skipped` conclusions as success. Returns an informational message when all checks pass.
|
|
495
|
+
|
|
496
|
+
No parameters.
|
|
497
|
+
|
|
498
|
+
<Note>
|
|
499
|
+
This policy requires [GitHub CLI](https://cli.github.com/) (`gh`) to be installed and authenticated.
|
|
500
|
+
Run `gh auth login` with a personal access token that has `repo` scope for read access to
|
|
501
|
+
Actions workflow runs. If `gh` is not installed or not authenticated, the policy fails open and reports the reason to Claude.
|
|
502
|
+
</Note>
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
401
506
|
## Beta policies
|
|
402
507
|
|
|
403
|
-
Some policies are marked `beta` and are not installed by default.
|
|
508
|
+
Some policies are marked `beta` and are not installed by default. Beta policies may have rough edges or generate false positives. They graduate to stable in future releases.
|
|
509
|
+
|
|
510
|
+
**Current beta policies:**
|
|
511
|
+
|
|
512
|
+
- `require-commit-before-stop` — commit all changes before stopping
|
|
513
|
+
- `require-push-before-stop` — push all commits to remote
|
|
514
|
+
- `require-pr-before-stop` — ensure a PR exists for the branch
|
|
515
|
+
- `require-ci-green-before-stop` — all CI checks must pass
|
|
516
|
+
|
|
517
|
+
Together, these enforce a **commit → push → PR → CI** workflow.
|
|
518
|
+
|
|
519
|
+
To install all beta policies:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
failproofai policies --install --beta
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Or install specific workflow policies:
|
|
404
526
|
|
|
405
527
|
```bash
|
|
406
|
-
failproofai --install-
|
|
528
|
+
failproofai policies --install require-commit-before-stop require-push-before-stop require-pr-before-stop require-ci-green-before-stop
|
|
407
529
|
```
|
|
408
530
|
|
|
409
|
-
|
|
531
|
+
Run `failproofai policies` to see which policies carry the beta flag.
|
|
410
532
|
|
|
411
533
|
---
|
|
412
534
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: View sessions
|
|
3
|
+
description: "Launch the dashboard to browse agent sessions and manage policies"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
failproofai
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Starts the web dashboard at `http://localhost:8020`.
|
|
11
|
+
|
|
12
|
+
## Options
|
|
13
|
+
|
|
14
|
+
| Flag | Description |
|
|
15
|
+
|------|-------------|
|
|
16
|
+
| `--port <number>` | Port to listen on (default: `8020`) |
|
|
17
|
+
| `--projects-path <path>` | Override where Claude Code project folders are found |
|
|
18
|
+
| `--allowed-origins <origins>` | Comma-separated hosts/IPs allowed to access dev resources |
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Launch on a different port
|
|
24
|
+
failproofai --port 9000
|
|
25
|
+
|
|
26
|
+
# Use a custom projects path
|
|
27
|
+
failproofai --projects-path ~/my-claude-projects
|
|
28
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Environment variables
|
|
3
|
+
description: "Configure failproofai behavior with environment variables"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Dashboard
|
|
7
|
+
|
|
8
|
+
| Variable | Description |
|
|
9
|
+
|----------|-------------|
|
|
10
|
+
| `PORT` | Dashboard port (default: `8020`) |
|
|
11
|
+
| `CLAUDE_PROJECTS_PATH` | Override where Claude Code project folders are found |
|
|
12
|
+
| `FAILPROOFAI_DISABLE_PAGES=policies,projects` | Comma-separated dashboard pages to hide |
|
|
13
|
+
| `FAILPROOFAI_ALLOWED_DEV_ORIGINS` | Hosts/IPs allowed to access dev resources. Same as `--allowed-origins`. |
|
|
14
|
+
|
|
15
|
+
## Logging
|
|
16
|
+
|
|
17
|
+
| Variable | Description |
|
|
18
|
+
|----------|-------------|
|
|
19
|
+
| `FAILPROOFAI_LOG_LEVEL=info\|warn\|error` | Server log level (default: `warn`) |
|
|
20
|
+
| `FAILPROOFAI_HOOK_LOG_FILE` | Custom hook log file path, or `true` for default (`~/.failproofai/logs/hooks.log`) |
|
|
21
|
+
|
|
22
|
+
## Telemetry
|
|
23
|
+
|
|
24
|
+
| Variable | Description |
|
|
25
|
+
|----------|-------------|
|
|
26
|
+
| `FAILPROOFAI_TELEMETRY_DISABLED=1` | Disable anonymous usage telemetry |
|
|
27
|
+
|
|
28
|
+
## LLM (for policy evaluation)
|
|
29
|
+
|
|
30
|
+
| Variable | Description |
|
|
31
|
+
|----------|-------------|
|
|
32
|
+
| `FAILPROOFAI_LLM_BASE_URL` | LLM API endpoint (default: `https://api.openai.com/v1`) |
|
|
33
|
+
| `FAILPROOFAI_LLM_API_KEY` | API key for LLM-powered policies |
|
|
34
|
+
| `FAILPROOFAI_LLM_MODEL` | Model name (default: `gpt-4o-mini`) |
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hook handler (internal)
|
|
3
|
+
description: "The subprocess Claude Code calls on each tool event"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
failproofai --hook <EventType>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
This is the command registered in Claude Code's `settings.json` by `failproofai policies --install`. You don't normally call this directly.
|
|
11
|
+
|
|
12
|
+
Reads a JSON payload from stdin, evaluates all enabled policies, and exits with a code indicating the decision:
|
|
13
|
+
|
|
14
|
+
| Exit code | Decision | Effect |
|
|
15
|
+
|-----------|----------|--------|
|
|
16
|
+
| `0` | `allow` | Permit the action |
|
|
17
|
+
| `1` | `deny` | Block the action - Claude sees the denial reason |
|
|
18
|
+
| `2` | `instruct` | Inject guidance into Claude's context |
|
|
19
|
+
|
|
20
|
+
### Supported event types
|
|
21
|
+
|
|
22
|
+
| Category | Events |
|
|
23
|
+
|----------|--------|
|
|
24
|
+
| **Tool execution** | `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` |
|
|
25
|
+
| **Session lifecycle** | `SessionStart`, `SessionEnd`, `Stop`, `StopFailure` |
|
|
26
|
+
| **User interaction** | `UserPromptSubmit`, `Notification`, `Elicitation`, `ElicitationResult` |
|
|
27
|
+
| **Subagents & tasks** | `SubagentStart`, `SubagentStop`, `TaskCreated`, `TaskCompleted`, `TeammateIdle` |
|
|
28
|
+
| **Configuration** | `InstructionsLoaded`, `ConfigChange`, `CwdChanged` |
|
|
29
|
+
| **File system** | `FileChanged`, `WorktreeCreate`, `WorktreeRemove` |
|
|
30
|
+
| **Context** | `PreCompact`, `PostCompact` |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Install policies
|
|
3
|
+
description: "Enable policies so they run on every agent tool call"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
failproofai policies --install [policy-names...] [options]
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Writes hook entries into Claude Code's `settings.json` so failproofai intercepts tool calls.
|
|
11
|
+
|
|
12
|
+
Aliases: `failproofai p -i`
|
|
13
|
+
|
|
14
|
+
## Options
|
|
15
|
+
|
|
16
|
+
| Flag | Description |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| `--scope user` | Install into `~/.claude/settings.json` (default - all sessions) |
|
|
19
|
+
| `--scope project` | Install into `.claude/settings.json` in the current directory |
|
|
20
|
+
| `--scope local` | Install into `.claude/settings.local.json` in the current directory |
|
|
21
|
+
| `--custom <path>` / `-c` | Path to a JS file containing custom hook policies |
|
|
22
|
+
| `--beta` | Include beta policies |
|
|
23
|
+
|
|
24
|
+
## Behavior
|
|
25
|
+
|
|
26
|
+
- **No policy names** - opens an interactive prompt to select policies
|
|
27
|
+
- **Specific names** - enables those policies (added to any already enabled)
|
|
28
|
+
- **`all`** - enables every available policy
|
|
29
|
+
|
|
30
|
+
Installation is additive: running `--install` again adds new policies without removing existing ones.
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Install all default policies globally (interactive)
|
|
36
|
+
failproofai policies --install
|
|
37
|
+
|
|
38
|
+
# Install specific policies for the current project
|
|
39
|
+
failproofai policies --install block-sudo sanitize-api-keys --scope project
|
|
40
|
+
|
|
41
|
+
# Enable all policies at once
|
|
42
|
+
failproofai policies --install all
|
|
43
|
+
|
|
44
|
+
# Install with a custom policies file
|
|
45
|
+
failproofai policies --install --custom ./my-policies.js
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
When `--custom <path>` is provided, the file is validated immediately - it must call `customPolicies.add()` at least once. The resolved path is saved to `policies-config.json` as `customPoliciesPath`.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: List policies
|
|
3
|
+
description: "See which policies are enabled, their parameters, and custom policies"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
failproofai policies
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Shows all policies with their status, configured parameters, and custom policies.
|
|
11
|
+
|
|
12
|
+
## Sample output
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
Failproof AI Hook Policies (user)
|
|
16
|
+
|
|
17
|
+
Status Name Description
|
|
18
|
+
────── ──────────────────────────────────────────────────────────────
|
|
19
|
+
✓ block-sudo Block sudo commands
|
|
20
|
+
allowPatterns: ["sudo systemctl status"]
|
|
21
|
+
✓ block-rm-rf Block recursive deletions
|
|
22
|
+
✗ block-curl-pipe-sh Block curl|bash patterns
|
|
23
|
+
✓ sanitize-api-keys Redact API keys from output
|
|
24
|
+
additionalPatterns: [{ regex: "MY_TOKEN_...", label: "..." }]
|
|
25
|
+
|
|
26
|
+
── Custom Policies (/home/alice/myproject/my-policies.js) ──────────────
|
|
27
|
+
✓ require-jira-ticket Block commits without ticket
|
|
28
|
+
✓ approval-gate Approval gate for destructive ops
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Unknown keys in `policyParams` are flagged here so you can catch typos early.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Uninstall policies
|
|
3
|
+
description: "Remove hook entries from Claude Code's settings"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
failproofai policies --uninstall [policy-names...] [options]
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Removes failproofai hook entries from Claude Code's `settings.json`.
|
|
11
|
+
|
|
12
|
+
Aliases: `failproofai p -u`
|
|
13
|
+
|
|
14
|
+
## Options
|
|
15
|
+
|
|
16
|
+
| Flag | Description |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| `--scope user` | Remove from global settings (default) |
|
|
19
|
+
| `--scope project` | Remove from project settings |
|
|
20
|
+
| `--scope local` | Remove from local settings |
|
|
21
|
+
| `--scope all` | Remove from all scopes at once |
|
|
22
|
+
| `--custom` / `-c` | Clear the `customPoliciesPath` from config |
|
|
23
|
+
| `--beta` | Remove only beta policies from config |
|
|
24
|
+
|
|
25
|
+
## Behavior
|
|
26
|
+
|
|
27
|
+
- **No policy names** - removes all failproofai hook entries from the settings file
|
|
28
|
+
- **Specific names** - disables those policies but keeps hooks installed
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Remove all hooks globally
|
|
34
|
+
failproofai policies --uninstall
|
|
35
|
+
|
|
36
|
+
# Disable a specific policy (keeps hooks installed)
|
|
37
|
+
failproofai policies --uninstall block-sudo
|
|
38
|
+
|
|
39
|
+
# Remove hooks from every scope
|
|
40
|
+
failproofai policies --uninstall --scope all
|
|
41
|
+
|
|
42
|
+
# Clear custom policies path
|
|
43
|
+
failproofai policies --uninstall --custom
|
|
44
|
+
```
|