Event bus automation system
Skill kjuhwa/skills-hub/skills/automation/event-bus-automation-system
Per-workspace event bus + handler registry (prompt / webhook / event-log) that turns typed events (LabelAdd, SchedulerTick, SessionStatusChange, PreToolUse) into config-driven actions defined in automations.json.From its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill event-bus-automation-systemAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.6 KB, 750 tokens by cl100k_base, as published. Nobody here has run it
Per-workspace automation event bus
When to use
- App where users should be able to say "when a session is labeled X, do Y" without writing code.
- You already emit typed events inside the app; you want to give users a config file that wires those events to side effects.
- Different workspaces should have independent automations (no global cross-talk).
How it works
- Define an
EventPayloadMap- a typed record of every event name to its payload shape (LabelAdd,LabelRemove,PermissionModeChange,FlagChange,SessionStatusChange,SchedulerTick,PreToolUse,PostToolUse,SessionStart,SessionEnd). - Per workspace, instantiate a
WorkspaceEventBus(typedEventEmitterwithon<K extends keyof EventMap>(event, handler)+emit<K>(event, payload)). - On startup, parse
<workspace>/automations.jsoninto a typedAutomationsConfig, validate with a schema (validateAutomationsConfig). - Register handlers for each event kind, each subscribing to the bus:
PromptHandler- fires a new agent session with a prompt, supports@mentions+ env var substitution ($CRAFT_LABEL,$CRAFT_SESSION_ID).WebhookHandler- POSTs a JSON payload to a user-configured URL.EventLogHandler- persistent audit trail under<workspace>/automations-history.jsonl.
- Matchers use a regex or filtrex expression against payload fields (
matcher: "^urgent$"orcron: "0 9 * * 1-5"for SchedulerTick). SchedulerServiceruns a separate minute tick and emitsSchedulerTickevents so cron-driven automations live in the same bus.- Single
dispose()call tears down handlers + bus + scheduler - no leaked timers.
Example
// workspace/automations.json
{
"version": 2,
"automations": {
"SchedulerTick": [
{ "cron": "0 9 * * 1-5", "timezone": "America/New_York",
"actions": [{ "type": "prompt", "prompt": "Daily @github triage" }] }
],
"LabelAdd": [
{ "matcher": "^urgent$",
"actions": [{ "type": "prompt", "prompt": "Triage $CRAFT_SESSION_ID" }] }
]
}
}
class AutomationSystem {
eventBus = new WorkspaceEventBus();
constructor(opts) {
this.promptHandler = new PromptHandler(this, opts);
this.webhookHandler = new WebhookHandler(this, opts);
this.eventLogHandler = new EventLogHandler(this, opts);
if (opts.enableScheduler) this.scheduler = new SchedulerService(this.eventBus);
}
emit<K extends keyof EventMap>(k: K, p: EventMap[K]) {
this.eventBus.emit(k, p);
this.eventLogHandler.record(k, p);
}
}
Gotchas
- Keep the event types in ONE file so they don't drift between emitter and listener.
- Schedule ticks should emit even when no automations subscribe - otherwise adding a cron rule requires restart.
- Regex matchers on user input are a footgun (ReDoS); consider length capping matcher strings.
env var substitutionneeds to whitelist - don't let users expand$CRAFT_API_KEYfrom config.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.