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.
Files changed (132) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  9. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  12. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.rsc +17 -17
  19. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +17 -17
  20. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  21. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +11 -11
  22. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  25. package/.next/standalone/.next/server/app/index.html +1 -1
  26. package/.next/standalone/.next/server/app/index.rsc +16 -16
  27. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  28. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -16
  29. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  30. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +11 -11
  31. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  32. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  33. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  36. package/.next/standalone/.next/server/app/policies/page.js +1 -1
  37. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  40. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  44. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  47. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/chunks/[root-of-the-server]__02nt~6d._.js +1 -1
  50. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
  51. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0a3kr67._.js → [root-of-the-server]__07k6eu-._.js} +2 -2
  52. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
  53. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
  54. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
  55. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
  56. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rbuarm._.js → [root-of-the-server]__0kfv9fw._.js} +2 -2
  57. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0osi8nq._.js → [root-of-the-server]__0okos0k._.js} +3 -3
  58. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +5 -4
  59. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
  60. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
  61. package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
  63. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
  64. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0rd0oc-._.js +1 -1
  65. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  66. package/.next/standalone/.next/server/pages/404.html +2 -2
  67. package/.next/standalone/.next/server/pages/500.html +1 -1
  68. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
  70. package/.next/standalone/.next/static/chunks/{0a08gn8709y98.js → 0.jo.465b6_k..js} +1 -1
  71. package/.next/standalone/.next/static/chunks/{0jhw8ofx.5g_e.js → 01haq0a3zrx0v.js} +1 -1
  72. package/.next/standalone/.next/static/chunks/08f78tecvx61l.css +1 -0
  73. package/.next/standalone/.next/static/chunks/{0mr-jhx402yci.js → 0a6xi1a8f_qlp.js} +1 -1
  74. package/.next/standalone/.next/static/chunks/{0qvj8bhl661lq.js → 0mq7ze1vkeo1p.js} +1 -1
  75. package/.next/standalone/.next/static/chunks/{0gcz-jqgqz~9m.js → 0p_fpyfmmohnx.js} +1 -1
  76. package/.next/standalone/.next/static/chunks/{0kob_5.phc~sk.js → 0qwyj3m400l_g.js} +1 -1
  77. package/.next/standalone/.next/static/chunks/{0mjc3aq2wxvlt.js → 0t94r_mk0s7e4.js} +1 -1
  78. package/.next/standalone/.next/static/chunks/{0q7z97izctgrw.js → 139~00zc9.u7s.js} +1 -1
  79. package/.next/standalone/Dockerfile.docs +12 -0
  80. package/.next/standalone/README.md +68 -55
  81. package/.next/standalone/bin/failproofai.mjs +221 -128
  82. package/.next/standalone/dist/cli.mjs +415 -106
  83. package/.next/standalone/dist/index.js +2 -2
  84. package/.next/standalone/docs/{architecture.md → architecture.mdx} +40 -23
  85. package/.next/standalone/docs/{built-in-policies.md → built-in-policies.mdx} +134 -12
  86. package/.next/standalone/docs/cli/dashboard.mdx +28 -0
  87. package/.next/standalone/docs/cli/environment-variables.mdx +34 -0
  88. package/.next/standalone/docs/cli/hook.mdx +30 -0
  89. package/.next/standalone/docs/cli/install-policies.mdx +48 -0
  90. package/.next/standalone/docs/cli/list-policies.mdx +31 -0
  91. package/.next/standalone/docs/cli/remove-policies.mdx +44 -0
  92. package/.next/standalone/docs/cli/version.mdx +12 -0
  93. package/.next/standalone/docs/{configuration.md → configuration.mdx} +16 -16
  94. package/.next/standalone/docs/{custom-hooks.md → custom-policies.mdx} +80 -42
  95. package/.next/standalone/docs/{dashboard.md → dashboard.mdx} +26 -29
  96. package/.next/standalone/docs/docs.json +31 -4
  97. package/.next/standalone/docs/examples.mdx +253 -0
  98. package/.next/standalone/docs/for-agents.mdx +38 -0
  99. package/.next/standalone/docs/getting-started.mdx +134 -0
  100. package/.next/standalone/docs/introduction.mdx +57 -0
  101. package/.next/standalone/docs/logo/dark.svg +21 -0
  102. package/.next/standalone/docs/logo/light.svg +21 -0
  103. package/.next/standalone/docs/{package-aliases.md → package-aliases.mdx} +5 -5
  104. package/.next/standalone/docs/{testing.md → testing.mdx} +11 -11
  105. package/.next/standalone/package.json +6 -9
  106. package/.next/standalone/scripts/publish-aliases.mjs +4 -2
  107. package/.next/standalone/skills-lock.json +10 -0
  108. package/.next/standalone/src/cli-error.ts +18 -0
  109. package/.next/standalone/src/hooks/builtin-policies.ts +259 -20
  110. package/.next/standalone/src/hooks/manager.ts +17 -3
  111. package/.next/standalone/src/hooks/policy-evaluator.ts +19 -1
  112. package/.next/standalone/src/hooks/policy-helpers.ts +2 -2
  113. package/.next/standalone/vitest.config.e2e.mts +3 -0
  114. package/.next/standalone/vitest.config.mts +3 -0
  115. package/README.md +68 -55
  116. package/bin/failproofai.mjs +221 -128
  117. package/dist/cli.mjs +415 -106
  118. package/dist/index.js +2 -2
  119. package/package.json +6 -9
  120. package/scripts/publish-aliases.mjs +4 -2
  121. package/src/cli-error.ts +18 -0
  122. package/src/hooks/builtin-policies.ts +259 -20
  123. package/src/hooks/manager.ts +17 -3
  124. package/src/hooks/policy-evaluator.ts +19 -1
  125. package/src/hooks/policy-helpers.ts +2 -2
  126. package/.next/standalone/.next/static/chunks/15jpradyu_531.css +0 -1
  127. package/.next/standalone/docs/cli-reference.md +0 -175
  128. package/.next/standalone/docs/getting-started.md +0 -128
  129. package/.next/standalone/docs/introduction.md +0 -47
  130. /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_buildManifest.js +0 -0
  131. /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_clientMiddlewareManifest.js +0 -0
  132. /package/.next/standalone/.next/static/{Dnk96sbMPjYOx1pdLdOH0 → 7fR022u1Sj-s5MfKO1q9Y}/_ssgManifest.js +0 -0
@@ -4,7 +4,7 @@ description: "Config file format, three-scope system, and merge rules"
4
4
  icon: gear
5
5
  ---
6
6
 
7
- failproofai uses JSON configuration files to control which policies are active, how they behave, and where custom hooks are loaded from.
7
+ 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.
8
8
 
9
9
  ---
10
10
 
@@ -22,9 +22,9 @@ When failproofai receives a hook event, it loads and merges all three files that
22
22
 
23
23
  ### Merge rules
24
24
 
25
- **`enabledPolicies`** the union of all three scopes. A policy enabled at any level is active.
25
+ **`enabledPolicies`** - the union of all three scopes. A policy enabled at any level is active.
26
26
 
27
- ```
27
+ ```text
28
28
  project: ["block-sudo"]
29
29
  local: ["block-rm-rf"]
30
30
  global: ["block-sudo", "sanitize-api-keys"]
@@ -32,16 +32,16 @@ global: ["block-sudo", "sanitize-api-keys"]
32
32
  resolved: ["block-sudo", "block-rm-rf", "sanitize-api-keys"] ← deduplicated union
33
33
  ```
34
34
 
35
- **`policyParams`** first scope that defines params for a given policy wins entirely. There is no deep merging of values within a policy's params.
35
+ **`policyParams`** - first scope that defines params for a given policy wins entirely. There is no deep merging of values within a policy's params.
36
36
 
37
- ```
37
+ ```text
38
38
  project: block-sudo → { allowPatterns: ["sudo apt-get update"] }
39
39
  global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
40
40
 
41
41
  resolved: { allowPatterns: ["sudo apt-get update"] } ← project wins, global ignored
42
42
  ```
43
43
 
44
- ```
44
+ ```text
45
45
  project: (no block-sudo entry)
46
46
  local: (no block-sudo entry)
47
47
  global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
@@ -49,9 +49,9 @@ global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
49
49
  resolved: { allowPatterns: ["sudo systemctl status"] } ← falls through to global
50
50
  ```
51
51
 
52
- **`customPoliciesPath`** first scope that defines it wins.
52
+ **`customPoliciesPath`** - first scope that defines it wins.
53
53
 
54
- **`llm`** first scope that defines it wins.
54
+ **`llm`** - first scope that defines it wins.
55
55
 
56
56
  ---
57
57
 
@@ -102,7 +102,7 @@ resolved: { allowPatterns: ["sudo systemctl status"] } ← falls through to glo
102
102
 
103
103
  Type: `string[]`
104
104
 
105
- List of policy names to enable. Names must match exactly the policy identifiers shown in `failproofai --list-policies`. See [Built-in Policies](./built-in-policies.md) for the full list.
105
+ List of policy names to enable. Names must match exactly the policy identifiers shown by `failproofai policies`. See [Built-in Policies](/built-in-policies) for the full list.
106
106
 
107
107
  Policies not in `enabledPolicies` are inactive, even if they have entries in `policyParams`.
108
108
 
@@ -110,19 +110,19 @@ Policies not in `enabledPolicies` are inactive, even if they have entries in `po
110
110
 
111
111
  Type: `Record<string, Record<string, unknown>>`
112
112
 
113
- Per-policy parameter overrides. The outer key is the policy name; the inner keys are policy-specific. Each policy documents its available parameters in [Built-in Policies](./built-in-policies.md).
113
+ Per-policy parameter overrides. The outer key is the policy name; the inner keys are policy-specific. Each policy documents its available parameters in [Built-in Policies](/built-in-policies).
114
114
 
115
115
  If a policy has parameters but you don't specify them, the policy's built-in defaults are used. Users who do not configure `policyParams` at all get identical behavior to previous versions.
116
116
 
117
- Unknown keys inside a policy's params block are silently ignored at hook-fire time but flagged as warnings when you run `failproofai --list-policies`.
117
+ Unknown keys inside a policy's params block are silently ignored at hook-fire time but flagged as warnings when you run `failproofai policies`.
118
118
 
119
119
  ### `customPoliciesPath`
120
120
 
121
121
  Type: `string` (absolute path)
122
122
 
123
- Path to a JavaScript file containing custom hook policies. This is set automatically by `failproofai --install-policies --custom <path>` (the path is resolved to absolute before being stored).
123
+ Path to a JavaScript file containing custom hook policies. This is set automatically by `failproofai policies --install --custom <path>` (the path is resolved to absolute before being stored).
124
124
 
125
- The file is loaded fresh on every hook event there is no caching. See [Custom Hooks](./custom-hooks.md) for authoring details.
125
+ The file is loaded fresh on every hook event - there is no caching. See [Custom Policies](/custom-policies) for authoring details.
126
126
 
127
127
  ### `llm`
128
128
 
@@ -143,10 +143,10 @@ LLM client configuration for policies that make AI calls. Not required for most
143
143
 
144
144
  ## Managing configuration from the CLI
145
145
 
146
- The `--install-policies` and `--remove-policies` commands write to Claude Code's `settings.json` (the hook entry points), while `policies-config.json` is the file you manage directly. The two are separate:
146
+ The `policies --install` and `policies --uninstall` commands write to Claude Code's `settings.json` (the hook entry points), while `policies-config.json` is the file you manage directly. The two are separate:
147
147
 
148
- - **`settings.json`** tells Claude Code to call `failproofai --hook <event>` on each tool use
149
- - **`policies-config.json`** tells failproofai which policies to evaluate and with what params
148
+ - **`settings.json`** - tells Claude Code to call `failproofai --hook <event>` on each tool use
149
+ - **`policies-config.json`** - tells failproofai which policies to evaluate and with what params
150
150
 
151
151
  You can edit `policies-config.json` directly at any time; changes take effect immediately on the next hook event with no restart needed.
152
152
 
@@ -1,10 +1,10 @@
1
1
  ---
2
- title: Custom Hooks
3
- description: "Write your own policies in JavaScript with allow, deny, and instruct decisions"
2
+ title: Custom Policies
3
+ description: "Write your own policies in JavaScript - enforce conventions, prevent drift, detect failures, integrate with external systems"
4
4
  icon: code
5
5
  ---
6
6
 
7
- Custom hooks let you write your own policies in JavaScript. They integrate with the same hook event system as built-in policies and support the same `allow`, `deny`, and `instruct` decisions.
7
+ 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.
8
8
 
9
9
  ---
10
10
 
@@ -32,7 +32,7 @@ customPolicies.add({
32
32
  Install it:
33
33
 
34
34
  ```bash
35
- failproofai --install-policies --custom ./my-policies.js
35
+ failproofai policies --install --custom ./my-policies.js
36
36
  ```
37
37
 
38
38
  ---
@@ -40,17 +40,17 @@ failproofai --install-policies --custom ./my-policies.js
40
40
  ## Installing and updating
41
41
 
42
42
  ```bash
43
- # Install with a custom hooks file
44
- failproofai --install-policies --custom ./my-policies.js
43
+ # Install with a custom policies file
44
+ failproofai policies --install --custom ./my-policies.js
45
45
 
46
- # Replace the hooks file path
47
- failproofai --install-policies --custom ./new-policies.js
46
+ # Replace the policies file path
47
+ failproofai policies --install --custom ./new-policies.js
48
48
 
49
- # Remove the custom hooks path from config
50
- failproofai --remove-policies --custom
49
+ # Remove the custom policies path from config
50
+ failproofai policies --uninstall --custom
51
51
  ```
52
52
 
53
- The resolved absolute path is stored in `policies-config.json` as `customPoliciesPath`. The file is loaded fresh on every hook event there is no caching between events.
53
+ The resolved absolute path is stored in `policies-config.json` as `customPoliciesPath`. The file is loaded fresh on every hook event - there is no caching between events.
54
54
 
55
55
  ---
56
56
 
@@ -64,12 +64,12 @@ import { customPolicies, allow, deny, instruct } from "failproofai";
64
64
 
65
65
  ### `customPolicies.add(hook)`
66
66
 
67
- Registers a hook. Call this as many times as needed for multiple hooks in the same file.
67
+ Registers a policy. Call this as many times as needed for multiple policies in the same file.
68
68
 
69
69
  ```ts
70
70
  customPolicies.add({
71
- name: string; // required unique identifier
72
- description?: string; // shown in --list-policies output
71
+ name: string; // required - unique identifier
72
+ description?: string; // shown in `failproofai policies` output
73
73
  match?: { events?: HookEventType[] }; // filter by event type; omit to match all
74
74
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
75
75
  });
@@ -79,13 +79,47 @@ customPolicies.add({
79
79
 
80
80
  | Function | Effect | Use when |
81
81
  |----------|--------|----------|
82
- | `allow()` | Permit the tool call | Nothing to block or warn about |
83
- | `deny(message)` | Block the tool call | The action should not proceed |
84
- | `instruct(message)` | Add context to Claude's prompt | You want Claude to be careful but not stopped |
82
+ | `allow()` | Permit the operation silently | The action is safe, no message needed |
83
+ | `deny(message)` | Block the operation | The agent should not take this action |
84
+ | `instruct(message)` | Add context without blocking | Give the agent extra context to stay on track |
85
85
 
86
- `deny(message)` the message appears to Claude prefixed with `"Blocked by failproofai:"`.
86
+ `deny(message)` - the message appears to Claude prefixed with `"Blocked by failproofai:"`. A single `deny` short-circuits all further evaluation.
87
87
 
88
- `instruct(message)` the message is appended to Claude's context for the current tool call. Multiple `instruct` returns from different hooks accumulate; a single `deny` short-circuits all further evaluation.
88
+ `instruct(message)` - the message is appended to Claude's context for the current tool call. The first `instruct` wins subsequent `instruct` returns from other policies are ignored.
89
+
90
+ ### Informational allow messages (beta)
91
+
92
+ <Note>
93
+ `allow(message)` is a beta feature available since v0.0.2-beta.3. The API may change in future releases. Earlier versions only support `allow()` without arguments.
94
+ </Note>
95
+
96
+ `allow(message)` permits the operation **and** sends an informational message back to Claude. The message is delivered as `additionalContext` in the hook handler's stdout response — the same mechanism used by `instruct`, but semantically different: it's a status update, not a warning.
97
+
98
+ | Function | Effect | Use when |
99
+ |----------|--------|----------|
100
+ | `allow(message)` | Permit and send context to Claude | Confirm a check passed, or explain why a check was skipped |
101
+
102
+ Use cases:
103
+ - **Status confirmations:** `allow("All CI checks passed.")` — tells Claude everything is green
104
+ - **Fail-open explanations:** `allow("GitHub CLI not installed, skipping CI check.")` — tells Claude why a check was skipped so it has full context
105
+ - **Multiple messages accumulate:** if several policies each return `allow(message)`, all messages are joined with newlines and delivered together
106
+
107
+ ```js
108
+ customPolicies.add({
109
+ name: "confirm-branch-status",
110
+ match: { events: ["Stop"] },
111
+ fn: async (ctx) => {
112
+ const cwd = ctx.session?.cwd;
113
+ if (!cwd) return allow("No working directory, skipping branch check.");
114
+
115
+ // ... check branch status ...
116
+ if (allPushed) {
117
+ return allow("Branch is up to date with remote.");
118
+ }
119
+ return deny("Unpushed changes detected.");
120
+ },
121
+ });
122
+ ```
89
123
 
90
124
  ### `PolicyContext` fields
91
125
 
@@ -111,25 +145,27 @@ customPolicies.add({
111
145
  |-------|--------------|----------------------|
112
146
  | `PreToolUse` | Before Claude runs a tool | The tool's input (e.g. `{ command: "..." }` for Bash) |
113
147
  | `PostToolUse` | After a tool completes | The tool's input + `tool_result` (the output) |
114
- | `Notification` | When Claude sends a notification | `{ message: "...", notification_type: "idle" \| "permission_prompt" \| ... }` hooks must always return `allow()`, they cannot block notifications |
148
+ | `Notification` | When Claude sends a notification | `{ message: "...", notification_type: "idle" \| "permission_prompt" \| ... }` - hooks must always return `allow()`, they cannot block notifications |
115
149
  | `Stop` | When the Claude session ends | Empty |
116
150
 
117
151
  ---
118
152
 
119
153
  ## Evaluation order
120
154
 
121
- Hooks are evaluated in this order:
155
+ Policies are evaluated in this order:
122
156
 
123
157
  1. Built-in policies (in definition order)
124
- 2. Custom hooks (in `.add()` order)
158
+ 2. Custom policies (in `.add()` order)
125
159
 
126
- The first `deny` short-circuits all subsequent hooks. All `instruct` returns accumulate into a single message regardless of which hook produced them.
160
+ <Note>
161
+ The first `deny` short-circuits all subsequent policies. The first `instruct` wins — subsequent `instruct` returns are ignored.
162
+ </Note>
127
163
 
128
164
  ---
129
165
 
130
166
  ## Transitive imports
131
167
 
132
- Custom hook files can import local modules using relative paths:
168
+ Custom policy files can import local modules using relative paths:
133
169
 
134
170
  ```js
135
171
  // my-policies.js
@@ -150,9 +186,9 @@ All relative imports reachable from the entry file are resolved. This is impleme
150
186
 
151
187
  ---
152
188
 
153
- ## Hook event type filtering
189
+ ## Event type filtering
154
190
 
155
- Use `match.events` to limit when a hook fires:
191
+ Use `match.events` to limit when a policy fires:
156
192
 
157
193
  ```js
158
194
  customPolicies.add({
@@ -172,34 +208,36 @@ Omit `match` entirely to fire on every event type.
172
208
 
173
209
  ## Error handling and failure modes
174
210
 
175
- Custom hooks are **fail-open**: errors never block built-in policies or crash the hook handler.
211
+ Custom policies are **fail-open**: errors never block built-in policies or crash the hook handler.
176
212
 
177
213
  | Failure | Behavior |
178
214
  |---------|----------|
179
- | `customPoliciesPath` not set | No custom hooks run; built-ins continue normally |
215
+ | `customPoliciesPath` not set | No custom policies run; built-ins continue normally |
180
216
  | File not found | Warning logged to `~/.failproofai/hook.log`; built-ins continue |
181
- | Syntax/import error | Error logged to `~/.failproofai/hook.log`; all custom hooks skipped |
217
+ | Syntax/import error | Error logged to `~/.failproofai/hook.log`; all custom policies skipped |
182
218
  | `fn` throws at runtime | Error logged; that hook treated as `allow`; other hooks continue |
183
219
  | `fn` takes longer than 10s | Timeout logged; treated as `allow` |
184
220
 
185
- To debug custom hook errors:
221
+ <Tip>
222
+ To debug custom policy errors, watch the log file:
186
223
 
187
224
  ```bash
188
225
  tail -f ~/.failproofai/hook.log
189
226
  ```
227
+ </Tip>
190
228
 
191
229
  ---
192
230
 
193
- ## Full example: multiple hooks
231
+ ## Full example: multiple policies
194
232
 
195
233
  ```js
196
234
  // my-policies.js
197
235
  import { customPolicies, allow, deny, instruct } from "failproofai";
198
236
 
199
- // Block any write to a path containing "secrets/"
237
+ // Prevent agent from writing to secrets/ directory
200
238
  customPolicies.add({
201
239
  name: "block-secrets-dir",
202
- description: "Block writes to secrets/ directory",
240
+ description: "Prevent agent from writing to secrets/ directory",
203
241
  match: { events: ["PreToolUse"] },
204
242
  fn: async (ctx) => {
205
243
  if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
@@ -209,10 +247,10 @@ customPolicies.add({
209
247
  },
210
248
  });
211
249
 
212
- // Remind Claude to check test results before committing
250
+ // Keep the agent on track: verify tests before committing
213
251
  customPolicies.add({
214
252
  name: "remind-test-before-commit",
215
- description: "Remind Claude to verify tests pass before committing",
253
+ description: "Keep the agent on track: verify tests pass before committing",
216
254
  match: { events: ["PreToolUse"] },
217
255
  fn: async (ctx) => {
218
256
  if (ctx.toolName !== "Bash") return allow();
@@ -224,10 +262,10 @@ customPolicies.add({
224
262
  },
225
263
  });
226
264
 
227
- // Block npm install during a freeze period
265
+ // Prevent unplanned dependency changes during freeze
228
266
  customPolicies.add({
229
267
  name: "dependency-freeze",
230
- description: "Block new package installs during freeze period",
268
+ description: "Prevent unplanned dependency changes during freeze period",
231
269
  match: { events: ["PreToolUse"] },
232
270
  fn: async (ctx) => {
233
271
  if (ctx.toolName !== "Bash") return allow();
@@ -245,17 +283,17 @@ export { customPolicies };
245
283
 
246
284
  ---
247
285
 
248
- ## Examples in the repository
286
+ ## Examples
249
287
 
250
- The `examples/` directory contains ready-to-run hook files:
288
+ The `examples/` directory contains ready-to-run policy files:
251
289
 
252
290
  | File | Contents |
253
291
  |------|----------|
254
- | `examples/policies-basic.js` | Five starter policies covering common use cases |
255
- | `examples/policies-advanced/index.js` | Advanced patterns including transitive imports, async calls, and `Stop` event hooks |
292
+ | `examples/policies-basic.js` | Five starter policies covering common agent failure modes |
293
+ | `examples/policies-advanced/index.js` | Advanced patterns: transitive imports, async calls, output scrubbing, and session-end hooks |
256
294
 
257
295
  Install the basic examples:
258
296
 
259
297
  ```bash
260
- failproofai --install-policies --custom ./examples/policies-basic.js
298
+ failproofai policies --install --custom ./examples/policies-basic.js
261
299
  ```
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  title: Dashboard
3
- description: "Session viewer, policy management, and activity log"
3
+ description: "Monitor agent sessions, review tool calls, and manage policies"
4
4
  icon: chart-line
5
5
  ---
6
6
 
7
- The failproofai dashboard is a local web application for browsing Claude Code sessions and managing security policies.
7
+ The failproofai dashboard is a local web application for monitoring your AI agent sessions and managing policies. See what your agents did while you were away.
8
8
 
9
9
  ---
10
10
 
@@ -16,13 +16,7 @@ failproofai
16
16
 
17
17
  Opens at `http://localhost:8020`.
18
18
 
19
- For production mode (faster startup, no file watching):
20
-
21
- ```bash
22
- failproofai --start
23
- ```
24
-
25
- The dashboard reads directly from the filesystem — your Claude Code project folders and the failproofai config files. Nothing is written to a remote service.
19
+ The dashboard reads directly from the filesystem - your Claude Code project folders and the failproofai config files. Nothing is written to a remote service.
26
20
 
27
21
  ---
28
22
 
@@ -53,11 +47,11 @@ Click a session to open the session viewer.
53
47
 
54
48
  ### Session viewer
55
49
 
56
- A timeline of everything that happened in a session:
50
+ The session viewer answers the key question for autonomous agents: what did the agent do, and did it stay on track? It shows a timeline of everything that happened in a session:
57
51
 
58
- - **Messages** Claude's text responses and user prompts
59
- - **Tool calls** Every tool Claude invoked, with its input and output
60
- - **Hook activity** For each tool call, which policies fired and what decision they returned
52
+ - **Messages** - Claude's text responses and user prompts
53
+ - **Tool calls** - Every tool Claude invoked, with its input and output
54
+ - **Policy activity** - For each tool call, which policies fired and what decision they returned
61
55
 
62
56
  The stats bar at the top shows session duration, total tool calls, and a summary of hook decisions (allow / deny / instruct counts).
63
57
 
@@ -67,24 +61,25 @@ You can export the session as a ZIP or JSONL file using the download button.
67
61
 
68
62
  A two-tab page for managing policies and reviewing activity.
69
63
 
70
- **Policies tab:**
71
-
72
- - Toggle individual policies on or off with a single click (writes to `~/.failproofai/policies-config.json`)
73
- - Expand a policy to configure its parameters (for policies that support `policyParams`)
74
- - Install or remove hooks for a given scope
75
- - Set a custom hooks file path
76
-
77
- **Activity tab:**
78
-
79
- - Full paginated history of every hook event that has fired across all sessions
80
- - Search by policy name, session ID, tool name, or decision
81
- - Each row shows: timestamp, policy name, decision, tool name, session ID, and the reason for deny/instruct decisions
64
+ <Tabs>
65
+ <Tab title="Policies tab">
66
+ - Toggle individual policies on or off with a single click (writes to `~/.failproofai/policies-config.json`)
67
+ - Expand a policy to configure its parameters (for policies that support `policyParams`)
68
+ - Install or remove hooks for a given scope
69
+ - Set a custom policies file path
70
+ </Tab>
71
+ <Tab title="Activity tab">
72
+ - Full paginated history of every hook event that has fired across all sessions
73
+ - Search by policy name, session ID, tool name, or decision
74
+ - Each row shows: timestamp, policy name, decision, tool name, session ID, and the reason for deny/instruct decisions
75
+ </Tab>
76
+ </Tabs>
82
77
 
83
78
  ---
84
79
 
85
80
  ## Auto-refresh
86
81
 
87
- The dashboard has an auto-refresh toggle in the top navigation. When enabled, the current page refreshes periodically to show new sessions and hook activity as they appear. Useful when you have an active Claude Code session running in parallel.
82
+ The dashboard has an auto-refresh toggle in the top navigation. When enabled, the current page refreshes periodically to show new sessions and policy activity as they appear. Essential for monitoring long-running autonomous agent sessions.
88
83
 
89
84
  ---
90
85
 
@@ -118,9 +113,9 @@ CLAUDE_PROJECTS_PATH=/custom/path/to/projects failproofai
118
113
 
119
114
  ## Accessing from a non-localhost host
120
115
 
121
- When running the dashboard in **dev mode** (`npm run dev`) and accessing it from a hostname other than `localhost` for example, a custom domain, a remote IP, or a tunneled URL you may see a warning like:
116
+ When running the dashboard in **dev mode** (`npm run dev`) and accessing it from a hostname other than `localhost` - for example, a custom domain, a remote IP, or a tunneled URL - you may see a warning like:
122
117
 
123
- ```
118
+ ```text
124
119
  ⚠ Blocked cross-origin request to Next.js dev resource /_next/webpack-hmr from "dashboard.example.com".
125
120
  ```
126
121
 
@@ -142,4 +137,6 @@ You can also set the `FAILPROOFAI_ALLOWED_DEV_ORIGINS` environment variable inst
142
137
  FAILPROOFAI_ALLOWED_DEV_ORIGINS=dashboard.example.com npm run dev
143
138
  ```
144
139
 
145
- > **Note:** This only applies to dev mode. When running `failproofai` (production mode), there is no HMR websocket and no cross-origin dev resource issue.
140
+ <Note>
141
+ This only applies to dev mode. When running `failproofai` (production mode), there is no HMR websocket and no cross-origin dev resource issue.
142
+ </Note>
@@ -7,6 +7,10 @@
7
7
  "light": "#e4587d",
8
8
  "dark": "#002CA7"
9
9
  },
10
+ "logo": {
11
+ "light": "/logo/exosphere-light.png",
12
+ "dark": "/logo/exosphere-dark.png"
13
+ },
10
14
  "favicon": "/favicon.ico",
11
15
  "navigation": {
12
16
  "tabs": [
@@ -23,15 +27,26 @@
23
27
  {
24
28
  "group": "Core Concepts",
25
29
  "pages": [
26
- "configuration",
27
30
  "built-in-policies",
28
- "custom-hooks"
31
+ "custom-policies",
32
+ "configuration"
33
+ ]
34
+ },
35
+ {
36
+ "group": "CLI",
37
+ "pages": [
38
+ "cli/dashboard",
39
+ "cli/install-policies",
40
+ "cli/remove-policies",
41
+ "cli/list-policies",
42
+ "cli/hook",
43
+ "cli/version",
44
+ "cli/environment-variables"
29
45
  ]
30
46
  },
31
47
  {
32
48
  "group": "Tools",
33
49
  "pages": [
34
- "cli-reference",
35
50
  "dashboard"
36
51
  ]
37
52
  },
@@ -40,7 +55,19 @@
40
55
  "pages": [
41
56
  "architecture",
42
57
  "testing",
43
- "package-aliases"
58
+ "package-aliases",
59
+ "for-agents"
60
+ ]
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "tab": "Examples",
66
+ "groups": [
67
+ {
68
+ "group": "Examples",
69
+ "pages": [
70
+ "examples"
44
71
  ]
45
72
  }
46
73
  ]