CLI commands
Hooks CLI
openclaw hooks
Inspect and configure internal hooks: handlers for command,
message, session, and Gateway events. Bare openclaw hooks runs the same report
as openclaw hooks list. These commands do not manage HTTP
Webhooks or the typed api.on(...) hook catalog in
Plugin hooks.
Target and scope
Read-only reports (hooks, list, info, check) first call hooks.status on
the selected Gateway. Configured remote Gateways and explicit
OPENCLAW_GATEWAY_URL targets are authoritative: missing remote URLs,
connection/authentication failures, and unsupported methods fail instead of
showing client-local hooks. An implicitly selected local Gateway can fall back
to local discovery when unavailable or when its hook-report method/agent
parameter is unsupported. Other errors are not silently replaced with local
inventory.
Enable, disable, install, and update mutate local files/config/state. They do
not change a remote Gateway over RPC. To change the server, run the command on
that host using its profile/config. Enable, disable, and config written by a new
install or link can activate immediately in the default hybrid
reload mode. off requires a manual
restart. Hook files and metadata are not watched. Restart after editing them or
updating existing hook code.
--agent <id> selects the agent workspace used for inspection. It is required
when configured agents do not have an implicit owner. Blank or unknown IDs
fail. The option works before or after list, info, check, enable, and
disable. It does not scope the persisted hook entry to that agent and is not
supported on install/update. See
Local, remote, and agent scope
for the distinction between workspace inventory and Gateway loading.
List hooks
openclaw hooks [--agent <id>] [--json]openclaw hooks list [--agent <id>] [--eligible] [--json] [-v|--verbose]Discovery includes bundled hooks, active plugin hooks, managed hooks, extra directories, and the selected workspace. Hook-name collisions follow the source policy.
| Option | Meaning |
|---|---|
--agent <id> |
Select the workspace to inspect. |
--eligible |
Show only loadable hooks: enabled by per-hook/source policy, requirements satisfied, and at least one declared event. |
--json |
Write structured JSON directly to stdout. Also accepted on the parent hooks command. |
-v, --verbose |
Add the Missing column to the human-readable table. |
Human output is a table with Status, Hook, Description, and Source columns,
preceded by Hooks (<ready>/<total> ready). Plugin-managed sources appear as
plugin:<id>.
List JSON
The root object contains workspaceDir, managedHooksDir, and hooks.
Each hook includes:
- Identity/display:
name,description,source, optionalpluginId,emoji,homepage, andmanagedByPlugin. - Status:
enabledByConfig,requirementsSatisfied,loadable, optionalblockedReason, plus compatibility aliaseseligible(loadable) anddisabled(!enabledByConfig). - Events/requirements:
events,unknownEvents, andmissing, whose arrays arebins,anyBins,env,config, andos.
blockedReason can be disabled in config, workspace hook (disabled by default),
missing requirements, or no events defined. Unknown events are
advisory: they do not by themselves make a hook unloadable.
Get hook info
openclaw hooks info <name> [--agent <id>] [--json]Accepts a hook name or its metadata hookKey. Exact hook names take precedence
over matching keys. A key must identify a single hook. Shows source, descriptor
and handler paths, homepage, events, unknown-event warnings, blocked reason, and
per-requirement status. A missing or ambiguous hook exits with code 1. An
ambiguous selector lists candidates so you can choose a unique name or key.
JSON includes the list fields plus filePath, baseDir, handlerPath,
hookKey, always, requirements, configChecks, and normalized install
options. Each config check has path and satisfied. Each install option has
id, kind, label, and bins. Install options are descriptive metadata, not
a command to install dependencies automatically.
Check eligibility
openclaw hooks check [--agent <id>] [--json]Prints totals for ready/not-ready hooks and lists blocking reasons. JSON has
total, eligible, notEligible, and hooks containing an eligible name
array and a notEligible array of { name, blockedReason?, missing } objects.
A successful report exits with code 0 even when hooks are not ready. For an automated eligibility gate, inspect the JSON counts rather than treating the exit code as an all-hooks-ready result. This still does not test actual loading.
Enable a hook
openclaw hooks enable <name> [--agent <id>]Discovers the hook locally, then writes
hooks.internal.entries.<hookKey>.enabled = true and
hooks.internal.enabled = true in local config. Other fields in that entry are
preserved. Exact hook names take precedence over matching keys. Ambiguous key
matches fail without writing.
Enable fails for a missing hook, a plugin-managed hook, or unmet runtime
requirements. It can enable a currently disabled workspace hook. This does not
prove a valid module export or event subscription. Inspect info and the
Gateway logs too.
The entry is global, even with --agent: it applies wherever that key is
discovered. Adding named entries can narrow a previously open-ended directory
selection. See Configuration.
The running Gateway reloads the selection in hybrid mode. If a selected hook
cannot load, it keeps the previous handlers. Inspect Gateway logs. Reload does
not replay gateway:startup, so boot-md runs on the next Gateway start.
Disable a hook
openclaw hooks disable <name> [--agent <id>]Writes hooks.internal.entries.<hookKey>.enabled = false. It does not remove the
hook files or change the master switch. Missing/ambiguous and plugin-managed
hooks are rejected. Missing runtime requirements do not prevent disabling.
In hybrid mode, subsequent events use the updated selection. An event already
running finishes with its original handlers.
Plugin-managed hooks cannot be toggled by these commands. Enable or disable the
owning plugin through openclaw plugins.
Install and update hook packs
Use the unified plugin installer for reviewed hook packs:
openclaw plugins install npm:<package>openclaw plugins install npm:<package>@<version> --pinopenclaw plugins install ./my-hook-packopenclaw plugins install ./my-hook-pack.tgz openclaw plugins update <id> --dry-runopenclaw plugins update <id>A pack declares hook directories in package.json under openclaw.hooks.
A local directory without package.json can contain a single HOOK.md and
handler. Copied hook packs are installed into <stateDir>/hooks/<id>. Their
hooks are enabled in config and install provenance is recorded in shared SQLite
state. That config can activate the hooks immediately in hybrid mode. Do not author
hooks.internal.installs in openclaw.json.
For the npm hook-pack path, specs are registry-only: package name with an
optional exact version or dist-tag. Git/URL/file specs, npm aliases, and semver
ranges are not npm registry specs. Bare specs and @latest stay on the stable
track. A prerelease resolution requires an explicit prerelease version or a
non-latest tag such as @beta or @rc. Use npm: to select npm explicitly. The
unified installer supports other plugin sources described in
openclaw plugins.
Supported local archives are .zip, .tgz, .tar.gz, and .tar. Copied hook
packs resolve runtime packages from dependencies and optionalDependencies,
including packs with only optional dependencies. Packages listed only in
devDependencies are omitted. npm pack and dependency installation use
--ignore-scripts. This does not sandbox the installed handler.
The download always creates an archive in OpenClaw's temporary workspace,
regardless of npm's dry-run or pack-destination settings.
Install options and trust
| Option | Effect for hook packs |
|---|---|
-l, --link |
Add the exact local hook or pack root to hooks.internal.load.extraDirs instead of copying it. Single hooks and nested pack layouts work. |
--pin |
Record the resolved exact npm name@version in install state when available; does not apply to local paths. |
--force |
Acknowledge a non-ClawHub source and allow replacement of an existing copied install. For links it acknowledges the source without copying. |
--acknowledge-install-policy-warning |
Acknowledge an operator security.installPolicy warning without its prompt. Blocks and policy failures still stop the install. |
Interactive non-ClawHub installs ask you to confirm trust. Noninteractive
installs require --force. Neither plugins install nor the hooks install
alias accepts a --yes flag. --force is also not a substitute for
acknowledging an install-policy warning. Review the source before supplying
either acknowledgement.
Update behavior
Updates use tracked npm install records. A tracked hook-pack ID uses its stored spec. A matching npm package spec can select a new version/tag. Local path and archive records are not refreshed by the npm hook updater.
--dry-run reports what would change without installing or rewriting config.
--all selects both plugins and hook packs in the unified updater, including
when reached through the deprecated alias. It is not a hooks-only bulk command.
When an applicable stored integrity hash differs from the downloaded artifact,
the updater warns and asks for confirmation in the terminal. No CLI flag answers
that prompt: neither plugins update nor the hooks update alias accepts
--yes, and --acknowledge-install-policy-warning covers only install-policy
warnings. --dry-run reports the drift without prompting.
Deprecated aliases
These commands print a deprecation warning and forward to the unified owners:
openclaw hooks install <path-or-spec> [-l|--link] [--pin] [--force] [--acknowledge-install-policy-warning]openclaw hooks update [id] [--all] [--dry-run] [--acknowledge-install-policy-warning]For update, provide id or --all. The aliases do not accept --agent and are
not the preferred interface for new automation.
Bundled hooks
The maintained catalog, event subscriptions, options, and verification notes
are in Bundled hooks. This includes
boot-md, bootstrap-extra-files, command-logger, compaction-notifier, and
session-memory (manual and automatic reset capture).
command-logger log file
On the Gateway host, with the default state directory:
tail -n 20 ~/.openclaw/logs/commands.logjq . ~/.openclaw/logs/commands.logjq 'select(.action == "new")' ~/.openclaw/logs/commands.logUse <stateDir>/logs/commands.log for a custom state directory. These records
contain session and sender identifiers. Protect access and arrange retention or
rotation. The hook does not rotate them.
Notes
Report commands support --json. Success JSON goes directly to stdout. Failures
use the standard CLI JSON failure envelope, and missing
hook info also includes the requested hook name. Reports do not execute a hook
as a test.
The hidden hooks relay command is reserved for generated native harness
integration. It is not an internal-hook testing or manual event-trigger command.