Skip to content

Community plugins for task events#626

Open
bborn wants to merge 2 commits into
mainfrom
task/4574-add-llmtrim-extension-to-taskyou-project
Open

Community plugins for task events#626
bborn wants to merge 2 commits into
mainfrom
task/4574-add-llmtrim-extension-to-taskyou-project

Conversation

@bborn

@bborn bborn commented Jun 30, 2026

Copy link
Copy Markdown
Owner

What

Makes TaskYou's event-hook system pluggable: community integrations install as self-contained, droppable directories instead of hand-placed scripts. Two capabilities so far — reactive hooks and user-invoked actions.

The gap

Task event hooks today are one script per event in a shared dir (~/.config/task/hooks/task.done). Two integrations that both care about task.done collide on the same file — no way to install several side by side.

Plugins

A plugin is a directory under ~/.config/task/plugins/ with a plugin.yaml manifest:

name: desktop-notify
version: 0.1.0
description: Native desktop notifications when a task finishes or needs you.
hooks:                      # fire automatically on events
  task.done: notify.sh
  task.blocked: notify.sh
actions:                    # user-invoked, on demand
  - id: test
    label: Send a test notification
    command: test-notify.sh

Drop the directory in and it's live. Any number of plugins can handle the same event, and all of them run — alongside the legacy single-script hook, which still works.

cp -R examples/plugins/desktop-notify ~/.config/task/plugins/
ty plugins list
ty plugins run desktop-notify test 42     # run an action against task #42

How it works

  • internal/hooks/plugins.go — manifest schema + forgiving discovery/validation. A malformed manifest, missing script, nameless plugin, or bad action entry is skipped (surfaced in ty plugins list / the daemon log), so one bad community plugin can't break a user's pipeline. A plugin needs ≥1 usable hook or action.
  • Hooks — on each event the Runner fans out to the legacy hook plus every matching plugin, concurrently in the background. Plugin hooks get TASK_PLUGIN_NAME / TASK_PLUGIN_DIR and run with cwd = the plugin dir. (Also moved the 30s timeout into the goroutine so a hook isn't cancelled the instant Run() returns.)
  • Actionsinternal/hooks/actions.go: RunAction runs an action synchronously (60s) with the task+plugin env; FindAction resolves plugin/action. Exposed via ty plugins run <plugin> <action> [task-id]. This is the shared runner all action surfaces use.
  • ty plugins list / ty plugins dir to inspect what's installed.
  • examples/plugins/desktop-notify/ — a complete plugin (hooks + an action).
  • docs/plugins.md + README — manifest format and authoring guide.

Built entirely on the existing hooks pipeline; no changes to the executor launch path.

Roadmap (discussed, not in this PR)

  • Action UI surfaces — a detail-view picker and command-palette entries, both on the RunAction runner above.
  • Plugin panes — turning the detail view's aux/shell slot into a tabbed container so a plugin (or the user) can add a command pane without touching the executor's "one per task" model. This is a focused refactor of detail.go and will land as its own PR.

Scope note

Plugins fire for the events the Runner dispatches today (task.started, task.done, task.blocked, task.failed, task.auth_required), documented in docs/plugins.md.

Test plan

  • go test ./internal/hooks/ — passing. Covers hook discovery (valid/multiple/sorted/missing-dir/invalid-skipped/partial-drop), an end-to-end fan-out test (legacy hook + two plugins fire on one event, plugin env asserted), and action validation + RunAction env injection (with and without a task) + FindAction.
  • go build ./..., go vet, gofmt clean.
  • golangci-lint run (v2.8.0, matching CI) — 0 issues.
  • Verified ty plugins list / ty plugins run against an installed copy of the example plugin.

🤖 Generated with Claude Code

Today task event hooks are one script per event in a shared dir, so two
integrations that both want e.g. task.done collide on the same file. This adds
plugins: a plugin is a self-contained directory under ~/.config/task/plugins/
with a plugin.yaml manifest declaring which events it handles. Drop it in and
it's active — any number of plugins can handle the same event and all run.

- internal/hooks/plugins.go: manifest schema + forgiving discovery/validation
  (a bad community plugin is skipped, not fatal).
- internal/hooks: Runner fans out each event to the legacy single-script hook
  plus every matching plugin, in the background. Plugin hooks get
  TASK_PLUGIN_NAME/TASK_PLUGIN_DIR and run with cwd set to the plugin dir.
- Move the 30s hook timeout into the background goroutine so the hook isn't
  cancelled the instant Run() returns.
- cmd/task: `ty plugins list` / `ty plugins dir` to inspect what's installed.
- examples/plugins/desktop-notify: a complete, copy-pasteable plugin.
- docs/plugins.md + README: manifest format and authoring guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bborn bborn force-pushed the task/4574-add-llmtrim-extension-to-taskyou-project branch from 8389ed4 to 046ce06 Compare June 30, 2026 16:13
@bborn bborn changed the title Add ty-llmtrim extension + plugin-architecture discussion Community plugins for task events Jul 1, 2026
Extends the plugin manifest with `actions`: user-triggered commands (vs. hooks,
which fire automatically on events). Each action has an id, optional label, and a
command script in the plugin dir. Plugins may now be actions-only.

- internal/hooks: Action type + validation (drop malformed/missing, keep rest);
  RunAction runs synchronously with task+plugin env, 60s timeout; FindAction.
- cmd/task: `ty plugins run <plugin> <action> [task-id]`; `ty plugins list` now
  shows actions with their run command.
- examples/plugins/desktop-notify: a `test` action.
- docs/plugins.md: actions section.

This is the shared runner for all three action surfaces; the CLI ships here, the
detail-view picker and command-palette entries build on it next.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant