Skip to content

Managed rollout

slopcop init writes the Stop hook into each user’s own settings. An administrator who manages Claude Code or Codex across a fleet can deploy the same hook through managed configuration instead. Where managed configuration allows only managed hooks, this is the only way the hook runs: the one init writes is a user hook, and it is blocked.

Managed configuration delivers the hook, not slopcop:

  • slopcop on PATH for the user the agent runs as. The hook command is slopcop hook claude or slopcop hook codex, and neither harness installs it. Use the same tooling that places the managed file; see Install the CLI.
  • A login. The hook checks with the user’s own credential: slopcop login, or SLOPCOP_TOKEN in the agent’s environment. See Sign in.
  • An enabled repository. The hook sends nothing for a repository the workspace does not have active, and never adds one. It stays dormant in a repository until someone runs slopcop enable there. See Repositories.

To check that the slopcop a user’s agent will find can run the hook, run it as that user with no input. It answers with a JSON systemMessage and exits 0:

Terminal window
$ slopcop hook claude </dev/null
{"systemMessage":"slopcop: could not read the Stop hook's payload, so no check ran."}

An older slopcop that cannot run the hook answers something else. The hook command ends in || true, so the agent still stops, but no check runs.

Users still get the skill from slopcop init --no-hooks, which installs the skill and leaves hooks alone. See The agent skill.

Claude Code reads hooks from managed settings, above every user and project file. Add SlopCop’s Stop handler to the hooks key of the managed settings you deploy, exactly as slopcop init writes it:

{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "slopcop hook claude || true",
"timeout": 720,
"statusMessage": "Checking the change with SlopCop"
}
]
}
]
}
}

As a file, that is managed-settings.json in Claude Code’s system directory, or a file of its own such as 50-slopcop.json in the managed-settings.d/ directory next to it, which Claude Code merges with the rest:

OSDirectory
macOS/Library/Application Support/ClaudeCode/
Linux and WSL/etc/claude-code/
WindowsC:\Program Files\ClaudeCode\

MDM profiles and server-managed settings take the same hooks key. Claude Code uses one managed source by default, so put the hook in the one in force on the machine. On one machine, /status in Claude Code names it on the Setting sources line.

Keep the handler identical to the one above:

  • The command. || true turns any failure of slopcop into one that lets the agent stop. Claude Code reads exit 2 from a Stop hook as an order to keep going, and a slopcop that cannot run the hook may exit 2.
  • The timeout. 720 seconds, so Claude Code waits longer than the hook’s own 10-minute wait for a check’s result.
  • The whole handler. Claude Code runs a handler that is defined the same way in several settings files once. A user who also runs slopcop init then gets one check, not two.

Under allowManagedHooksOnly, Claude Code blocks user, project, and local hooks, including the one slopcop init writes to ~/.claude/settings.json; only the managed hook runs. Without it, user hooks run beside managed ones, and a user’s slopcop init --remove-hooks removes only their own copy, never the managed one.

Codex reads managed hooks inline from the [hooks] table of its managed requirements.toml. Hooks there are trusted by policy, so users skip the /hooks trust step that the hook slopcop init writes needs, and they cannot turn the hook off from Codex’s hook browser.

[hooks]
[[hooks.Stop]]
[[hooks.Stop.hooks]]
type = "command"
command = "slopcop hook codex || true"
command_windows = "slopcop hook codex || exit /b 0"
timeout = 720

The Windows command differs because Codex runs hooks there through cmd, which has no true.

Codex does not install anything from managed_dir; device management must put slopcop on PATH itself, as above.

allow_managed_hooks_only = true makes Codex ignore user, project, session, and plugin hooks, including the one in ~/.codex/hooks.json that slopcop init writes. Without it, give users slopcop init --no-hooks, so they are not also asked to trust a second copy of the hook.