Events
Sometimes declaring files and packages isn’t enough—you need to do something after a
sync, like reloading a service once its config file changes or rebuilding a cache. Modules
can hook into the sync with onEverySync.
onEverySync
Section titled “onEverySync”A module may define an optional onEverySync hook. It runs once per sysdef sync, after
files have been linked and packages have been installed/removed:
export interface Module { // ... readonly onEverySync?: (s: Shell) => Promise<void>;}The hook receives the same Shell function providers use, so it obeys dry-run mode: during
sysdef sync --dry-run it’s handed dryShell (which only logs the commands it would
run) instead of actually executing anything.
Example
Section titled “Example”import type { ModuleGenerator } from "../sysdef-src/sysdef";
const generator: ModuleGenerator = (shell) => { return { name: "desktop", variables: {}, packages: { "arch-official": ["waybar"], }, directories: { "{HOMEDIR}/.config/waybar": "./config/waybar", }, files: {}, // reload waybar so it picks up the config we just linked onEverySync: async (shell) => { await shell("killall -SIGUSR2 waybar", { throwOnError: false, // fine if it isn't running yet displayOutput: true, }); }, };};
export default generator;Other common uses:
onEverySync: async (shell) => { // restart a user service after its unit/config changed await shell("systemctl --user restart example.service", { displayOutput: true });
// run a setup script that lives in your sysdef directory await shell("bash ./scripts/post-sync.sh", { displayOutput: true });
// something that needs root — use asRoot, never a hard-coded sudo await shell("fc-cache -f", { asRoot: true, displayOutput: true });}- The hook runs on every sync, so make it idempotent—it should be safe to run repeatedly. Reloading a service or refreshing a cache is fine; one-time bootstrap steps are not a good fit.
- It runs even when there were no package or file changes on that particular sync.
- Use
throwOnError: falsefor commands that may legitimately fail (for example signalling a program that isn’t running yet); otherwise a non-zero exit will abort the sync. - For running privileged commands, pass
{ asRoot: true }rather than prefixingsudo—see Providers.
See Modules for the rest of the module shape.