Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

continuedev/pollhook

Repository files navigation

pollhook

Poll REST APIs, deliver webhooks. Bridge any API into Continue's event system.

An autonomous codebase built by the Continue Software Factory


Why?

Many services (Sentry, PagerDuty, Snyk, etc.) have REST APIs but no outgoing webhooks. Setting up custom integrations for each one means writing bespoke glue code, managing state, and handling retries -- over and over.

pollhook does one thing: run a command on an interval, detect new items via ID-based dedup, and POST them to a webhook endpoint. One YAML file replaces all that glue.

Table of Contents

  • Quick Start
  • Config Format
  • Commands
  • How It Works
  • Design Decisions
  • Contributing
  • License

Quick Start

# Build from source
git clone https://github.com/continuedev/pollhook.git
cd pollhook
make build

# Or install directly
go install github.com/continuedev/pollhook@latest

Create a pollhook.yaml:

sources:
- name: sentry-issues
command: |
curl -s -H "Authorization: Bearer $SENTRY_TOKEN" \
https://sentry.io/api/0/projects/my-org/my-project/issues/?query=is:unresolved
interval: 5m
items: "."
id: "id"
webhook:
url: https://hub.continue.dev/api/webhooks/ingest/your-workflow-id
secret: your-webhook-secret
# Dry run -- validate config, show extracted items
pollhook test --config pollhook.yaml

# Run for real
pollhook serve --config pollhook.yaml

Config Format

sources:
- name: sentry-issues # Unique name for this source
command: | # Shell command (run via sh -c) that outputs JSON
curl -s -H "Authorization: Bearer $SENTRY_TOKEN" \
https://sentry.io/api/0/projects/my-org/my-project/issues/
interval: 5m # Poll interval (Go duration: 30s, 2m, 1h)
items: "." # Dot path to the JSON array ("." = root)
id: "id" # Dot path to unique ID on each item
webhook:
url: https://... # Webhook endpoint URL
secret: optional # Sent as X-Webhook-Secret header

Dot paths: "." means the root is the array. "data.incidents" navigates $.data.incidents. Environment variables in the config are expanded via $VAR or ${VAR}.

Commands

pollhook serve

Run pollers and deliver webhooks.

pollhook serve --config pollhook.yaml [--state-dir ~/.pollhook]
  • Starts a goroutine per source with time.Ticker
  • Polls immediately on startup, then on interval
  • State persisted to ~/.pollhook/state.json every 30s and on shutdown
  • Graceful shutdown on SIGINT/SIGTERM

pollhook test

Validate config, run each command once, show extracted items. No webhooks sent, no state touched.

pollhook test --config pollhook.yaml

pollhook version

Print the version.

How It Works

For each source, a goroutine runs on a timer:

  1. Execute command -- sh -c with 60s timeout, capture stdout
  2. Extract items -- parse JSON, navigate dot path to array
  3. Extract ID -- get unique ID from each item via dot path
  4. Dedup -- skip if ID already seen (checked against persisted state)
  5. Deliver webhook -- POST {"source": "name", "item": {...}, "polled_at": "..."} to the webhook URL
  6. Mark seen -- only after successful delivery (at-least-once guarantee)

The webhook payload matches what Continue's /api/webhooks/ingest/:workflowId endpoint expects -- any JSON body that gets stringified into the workflow prompt.

Design Decisions

Decision Choice Why
Dependencies Only gopkg.in/yaml.v3 Everything else is stdlib
CLI framework flag.FlagSet 2 commands don't justify cobra
Change detection ID-based dedup Deterministic, order-independent, per-item
State cap 10,000 IDs per source Sliding window prevents unbounded growth
Delivery guarantee At-least-once Failed delivery = ID stays unseen = retried next tick
Retry 1 retry on 5xx (2s delay) 4xx = config error, 5xx = transient
Command execution sh -c Lets users write piped multi-line commands
Webhook secret X-Webhook-Secret header Matches ingest endpoint's timing-safe comparison

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

Apache-2.0 -- see LICENSE for details. Copyright (c) 2025 Continue Dev, Inc.

About

Poll REST APIs, deliver webhooks. Bridge any API into Continue's event system.

Topics

Resources

Readme

License

Apache-2.0 license

Contributing

Contributing

Security policy

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors