Private bobbins and hooks¶
A deployment never edits a built-in bobbin. When a built-in bobbin does not do what you need, there are three ways to change that, from the lightest to the heaviest.
1. Settings¶
Almost everything a bobbin lets you tune is a setting: a time zone, working hours, domains to skip, a state directory.
Set them in the instance's settings table. hookspool bobbin show <vendor>.<product> lists them with their types and defaults.
2. A hooks module¶
A bobbin that supports hooks has a hooks setting, an absolute path to a Python file of yours. The bobbin's README names
the functions it calls and their signatures. For example:
| bobbin | function | purpose |
|---|---|---|
google.gmail |
hooks.classify(message, account, ctx) -> dict or None |
hand a message off privately before the bobbin's own rules run |
google.calendar |
hooks.travel(event, day_events, ctx) -> dict or None |
decide about travel blocks around an event |
The function receives the processor context (ctx.settings, ctx.http, ctx.load_state and so on). A hook that raises
retries the batch and changes nothing. The rules that keep a built-in bobbin small do not apply to hooks, because a hooks
module is your code, not the bobbin's.
[bobbins.gmail]
bobbin = "google.gmail"
[bobbins.gmail.settings]
owner = "owner@example.com"
hooks = "/etc/hookspool/hooks/gmail_hooks.py"
Write settings as a table of its own, as here. An inline settings = { ... } cannot be added to later, so the
rule_packs and [[bobbins.gmail.settings.rules]] lines of Mail rules would then not parse.
3. A private bobbin¶
When the service is not in the repository at all, write a bobbin (Writing a bobbin) in a directory of your own and list the parent directory in the config:
A bobbin is <dir>/<vendor>/<product>/ under a bobbin_path entry (named <vendor>.<product>), searched after the built-in
ones. The vendor directory holds nothing else, and a flat subdirectory is reported as an error. It may not share a name with a
built-in bobbin. It is loaded by file path under a private module name and is never added to sys.path, so it cannot
shadow another module. hookspool bobbin list shows where each one came from, and hookspool bobbin check <dir> runs the
same checks on it as on a bobbin in the repository.
What the loader insists on¶
Code loaded by path, whether a bobbin_path directory or a hooks module, must be an absolute path to a regular file or
directory that is not writable by its group or by others, and is owned by root or by the user hookspool runs as.
hookspool check verifies this the same way it verifies secret files.
Manifests and bobbin directories are read again on every config load. Editing a bobbin.toml or adding a directory does not
change config.toml, so it takes effect at the next hookspool reload or service restart. Processor code and hooks modules
are loaded fresh by each processor run, so a change applies to the next batch.