You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[CLAUDE ROUTINE]: CX/Reliability enhancement — add a confirmation step (or --yes) to failproofai policies --uninstall --scope all so a single typo can't sweep hooks out of every scope at once #268
failproofai policies --uninstall --scope all is the only --scope value that fans out across every Claude Code settings file the user owns (user / project / local) and clears enabledPolicies, customPoliciesPath, and policyParams from each scope. That fan-out is exactly what users want when they intentionally reach for it — but it currently runs without any "are you sure?" gate, so a one-character typo (or a --scope all autocomplete dropping in unintentionally) wipes the entire setup in one command.
Adding a tiny interactive confirmation (skippable with --yes for CI) keeps the existing happy path fast for power users while removing the "oh no, I lost my whole config" footgun for everyone else.
Where
bin/failproofai.mjs:328-386 — the uninstall branch parses --scope and goes straight to removeHooks(...) with no prompt:
constscopeIdx=subArgs.indexOf("--scope");constscope=scopeIdx>=0 ? subArgs[scopeIdx+1] : "user";// ...validation...awaitremoveHooks(policyNames.length>0 ? policyNames : undefined,scope,// ← can be "all"undefined,{ betaOnly, removeCustomHooks, cli },);
src/hooks/manager.ts:272-424 — the removeHooks() body fans scope === "all" across every scope of every selected CLI and clears the shared policyParams / customPoliciesPath from every scope's config:
constscopesToRemove: HookScope[]=scope==="all"
? [...integration.scopes]
: integration.scopes.includes(scope) ? [scope] : [];// ...if(scope==="all"){// Clear config across all three scopesfor(constsofHOOK_SCOPES){constexisting=readScopedHooksConfig(s,cwd);if(existing.enabledPolicies.length>0||existing.customPoliciesPath||existing.policyParams){const{customPoliciesPath: _drop,policyParams: _dropParams, ...rest}=existing;// …writes empty config back…}}}
So a single command edits Claude / Codex / Copilot / Cursor settings across user + project + local + clears ~/.failproofai/policies-config.json, <repo>/.failproofai/policies-config.json, and <repo>/.failproofai/policies-config.local.json — all without asking.
Why this matters
flowchart TD
A[User wants to uninstall hooks at project scope] --> B{Types command}
B -->|--scope project ✅| C[Removes only project scope]
B -->|--scope all 🚨 typo or autocomplete| D[Removes from user + project + local + every CLI]
D --> E[customPoliciesPath cleared]
D --> F[policyParams cleared]
D --> G[enabledPolicies cleared in every scope file]
E --> H[User: 'wait, where did my custom policies go?']
F --> H
G --> H
H --> I[Re-discover paths, re-pick policies, re-tune params]
I --> J[~10–30 minutes of recovery]
A2[CI / scripted uninstall] --> B2[--scope all --yes]
B2 --> K[Skips prompt cleanly]
Loading
Concrete scenarios we already see in support traffic-shaped questions:
Tab-completion drift. The user types --scope p and tab-completes to --scope project, fat-fingers, deletes the roject, hits enter. --scope all is a valid value too, so there's no error, just a sweeping uninstall.
Copy-paste from a teammate's runbook. Internal docs that say "to fully reset, run failproofai policies --uninstall --scope all" get copy-pasted into a project shell when the user only wanted to wipe the project scope.
Recovery cost is non-trivial.customPoliciesPath and policyParams are getting cleared from every scope at once — not just hook registrations — so the user has to re-locate their custom file and re-tune any policy params they had set. That's exactly the work --install was supposed to make easy.
The good news: this is a tiny CX add that keeps the existing happy path fast, and gives CI a clean opt-out via a --yes flag.
Proposed enhancement
Two complementary tightenings — implement together:
Interactive confirmation when --scope all is used and stdin is a TTY. Show a one-screen summary of exactly what will be cleared, then prompt Continue? [y/N]. Default no.
if(scope==="all"&&process.stdin.isTTY&&!args.includes("--yes")){constaffectedClis=selectedClis.map((c)=>getIntegration(c).displayName).join(", ");console.log(`This will remove failproofai hooks from ALL scopes for ${affectedClis}:`);for(constcliIdofselectedClis){constintegration=getIntegration(cliId);for(constsofintegration.scopes){console.log(` • ${integration.displayName} / ${s}: ${integration.getSettingsPath(s,cwd)}`);}}console.log(`It will also clear customPoliciesPath, policyParams, and enabledPolicies from every scope's config.`);constok=awaitprompt("Continue? [y/N] ");if(!/^y(es)?$/i.test(ok.trim())){thrownewCliError("Aborted by user.");}}
--yes (alias -y) flag to suppress the prompt, so anyone scripting the cleanup (CI cleanup jobs, install-test scripts) has a clear opt-out. Documented under policies --uninstall in --help.
Composability note: re-use the same prompt helper (or extract one) that the interactive policy selector already uses, so non-TTY callers (CI) still go straight through with --yes.
Acceptance criteria
In a TTY, failproofai policies --uninstall --scope all shows the affected paths and prompts Continue? [y/N] with default no.
--yes / -y skips the prompt for scripted use.
Non-TTY stdin (e.g. failproofai policies --uninstall --scope all < /dev/null in CI) without--yes aborts with a clear error explaining --yes is required.
--scope user|project|local paths are unchanged (no prompt).
Summary
failproofai policies --uninstall --scope allis the only--scopevalue that fans out across every Claude Code settings file the user owns (user / project / local) and clearsenabledPolicies,customPoliciesPath, andpolicyParamsfrom each scope. That fan-out is exactly what users want when they intentionally reach for it — but it currently runs without any "are you sure?" gate, so a one-character typo (or a--scope allautocomplete dropping in unintentionally) wipes the entire setup in one command.Adding a tiny interactive confirmation (skippable with
--yesfor CI) keeps the existing happy path fast for power users while removing the "oh no, I lost my whole config" footgun for everyone else.Where
bin/failproofai.mjs:328-386— the uninstall branch parses--scopeand goes straight toremoveHooks(...)with no prompt:src/hooks/manager.ts:272-424— theremoveHooks()body fansscope === "all"across every scope of every selected CLI and clears the sharedpolicyParams/customPoliciesPathfrom every scope's config:So a single command edits Claude / Codex / Copilot / Cursor settings across user + project + local + clears
~/.failproofai/policies-config.json,<repo>/.failproofai/policies-config.json, and<repo>/.failproofai/policies-config.local.json— all without asking.Why this matters
flowchart TD A[User wants to uninstall hooks at project scope] --> B{Types command} B -->|--scope project ✅| C[Removes only project scope] B -->|--scope all 🚨 typo or autocomplete| D[Removes from user + project + local + every CLI] D --> E[customPoliciesPath cleared] D --> F[policyParams cleared] D --> G[enabledPolicies cleared in every scope file] E --> H[User: 'wait, where did my custom policies go?'] F --> H G --> H H --> I[Re-discover paths, re-pick policies, re-tune params] I --> J[~10–30 minutes of recovery] A2[CI / scripted uninstall] --> B2[--scope all --yes] B2 --> K[Skips prompt cleanly]Concrete scenarios we already see in support traffic-shaped questions:
--scope pand tab-completes to--scope project, fat-fingers, deletes theroject, hits enter.--scope allis a valid value too, so there's no error, just a sweeping uninstall.failproofai policies --uninstall --scope all" get copy-pasted into a project shell when the user only wanted to wipe the project scope.customPoliciesPathandpolicyParamsare getting cleared from every scope at once — not just hook registrations — so the user has to re-locate their custom file and re-tune any policy params they had set. That's exactly the work--installwas supposed to make easy.The good news: this is a tiny CX add that keeps the existing happy path fast, and gives CI a clean opt-out via a
--yesflag.Proposed enhancement
Two complementary tightenings — implement together:
Interactive confirmation when
--scope allis used and stdin is a TTY. Show a one-screen summary of exactly what will be cleared, then promptContinue? [y/N]. Default no.--yes(alias-y) flag to suppress the prompt, so anyone scripting the cleanup (CI cleanup jobs, install-test scripts) has a clear opt-out. Documented underpolicies --uninstallin--help.Composability note: re-use the same prompt helper (or extract one) that the interactive policy selector already uses, so non-TTY callers (CI) still go straight through with
--yes.Acceptance criteria
failproofai policies --uninstall --scope allshows the affected paths and promptsContinue? [y/N]with default no.--yes/-yskips the prompt for scripted use.failproofai policies --uninstall --scope all < /dev/nullin CI) without--yesaborts with a clear error explaining--yesis required.--scope user|project|localpaths are unchanged (no prompt).__tests__/hooks/manager.test.ts(orbintest once the bin tests from [CLAUDE ROUTINE]: Test enhancement — add unit tests forbin/failproofai.mjsCLI dispatch, unknown-flag suggestions, and exit-code contract #255 land) covering: TTY-confirm, TTY-decline,--yesskip, non-TTY abort.--help/policies --helpdocuments the new prompt and--yesflag.## Unreleased > Features(orFixesif framed as a guardrail).