A Node.js CLI tool that monitors tech products for new release notes, summarizes them with a local AI model via Ollama, and posts the summaries to Slack.
- You configure one or more connectors — each one knows how to fetch release notes from a specific source
- Dronewire runs a persistent Express server that schedules cron jobs for each connector
- When a connector fires, it fetches new releases, filters out anything already seen, summarizes each one with Ollama, and posts to Slack
- The CLI talks to the server to manage connectors and trigger manual checks
- Node.js >= 24
- Ollama running locally (or accessible over the network)
- A Slack bot token with
chat:writepermission
npm install -g dronewire1. Copy the config template
mkdir -p ~/.dronewire
cp $(npm root -g)/dronewire/dronewire.config.js ~/.dronewire/dronewire.config.js2. Edit ~/.dronewire/dronewire.config.js
At minimum, set your Slack token and add at least one connector (see Configuration below).
3. Start the server (keep this terminal open)
dronewire server start4. Test a connector without posting to Slack
dronewire check my-connector --dry-runThe config file is a JS module at ~/.dronewire/dronewire.config.js (override with --config <path>).
export default {
server: {
port: 3847,
host: 'localhost',
},
ollama: {
host: 'http://localhost:11434',
model: 'llama3.2',
systemPrompt: 'Summarize these release notes in 2-3 concise bullet points.',
},
slack: {
enabled: true,
token: 'xoxb-your-token-here',
centralChannel: '#releases', // all summaries go here; null to disable
},
connectors: [
{
id: 'my-wordpress', // unique ID used in CLI commands
type: 'wordpress', // builtin connector type
config: {
url: 'https://example.com',
},
schedule: '0 9 * * *', // cron schedule
initialLookbackDate: '2025-01-01T00:00:00Z', // cutoff for first run
slackChannel: '#my-releases', // per-connector channel (null to skip)
disableCentralChannel: false, // set true to opt out of centralChannel
},
],
}| Field | Required | Description |
|---|---|---|
id |
Yes | Unique identifier used in CLI commands |
type |
Yes | wordpress (builtin) or custom |
config |
Yes | Connector-specific config (passed to the connector class) |
schedule |
Yes | Cron expression for how often to check |
initialLookbackDate |
No | ISO date used as the cutoff on the very first run when no state exists |
slackChannel |
No | Slack channel to post this connector's summaries to |
disableCentralChannel |
No | Set true to opt this connector out of slack.centralChannel (default: false) |
disableCron |
No | Set true to permanently skip scheduling, regardless of state (default: false) |
systemPrompt |
No | Override the global Ollama system prompt for this connector only |
For each new release, summaries are posted to:
- The connector's own
slackChannel(if set) - The global
slack.centralChannel(if set, anddisableCentralChannelis nottrue)
If both are set, the summary goes to both. Set slack.disabled: true to disable all Slack output and log summaries to the console instead.
Start the Dronewire server in the foreground. Keep this running in a dedicated terminal tab.
dronewire server start
dronewire server start --config /path/to/dronewire.config.jsCheck whether the server is reachable.
dronewire server statusList all configured connectors and their current state.
dronewire listOutput columns: id, status, schedule, slack channel, last processed date
Manually run a connector check. Runs inline by default (no server required).
dronewire check my-wordpress
dronewire check my-wordpress --dry-run # skip Slack, log to console
dronewire check my-wordpress --via-server # delegate to the running serverPause or resume all cron jobs globally.
dronewire cron enable
dronewire cron disablePause or resume the cron job for a specific connector. State is persisted to ~/.dronewire/dronewire.state.json.
dronewire cron enable-connector my-wordpress
dronewire cron disable-connector my-wordpressFetches posts from the WordPress REST API.
{
type: 'wordpress',
config: {
url: 'https://example.com', // required — base URL of the WordPress site
perPage: 5, // optional — posts per request (default: 10)
categories: [1, 2], // optional — filter by category IDs
tags: [3], // optional — filter by tag IDs
},
}Create a JS file that exports a class extending BaseConnector:
import { BaseConnector } from 'dronewire/src/connectors/BaseConnector.js';
export default class MyConnector extends BaseConnector {
// Required — return an array of release objects
async fetchReleases() {
const res = await fetch('https://api.example.com/releases');
return res.json();
}
// Required — return a Date for a given release
parseReleaseDate(release) {
return new Date(release.published_at);
}
// Optional — format a release for the AI prompt (defaults to JSON.stringify)
formatForAI(release) {
return `${release.name}\n\n${release.body}`;
}
// Optional — override the system prompt for this connector
getSystemPrompt() {
return 'Summarize this changelog entry in one sentence.';
}
}Register it in your config:
{
id: 'my-service',
type: 'custom',
script: '/path/to/MyConnector.js',
config: {
// anything you want — available as this.config inside the class
},
schedule: '0 10 * * *',
initialLookbackDate: '2025-01-01T00:00:00Z',
slackChannel: '#my-service-releases',
}Dronewire tracks which releases have already been processed in ~/.dronewire/dronewire.state.json. You can inspect or reset it manually if needed. Per-connector cronDisabled flags written by the CLI are also stored here.
The server exposes a simple HTTP API that the CLI uses. You can call it directly if you want to build integrations or a web UI.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness check |
GET |
/connections |
List connectors with full state |
POST |
/connections/:id/check |
Trigger a manual check ({ dryRun: true } body optional) |
GET |
/crons |
List cron job statuses |
POST |
/crons/enable |
Enable global cron |
POST |
/crons/disable |
Disable global cron |
POST |
/crons/:id/enable |
Enable a connector's cron |
POST |
/crons/:id/disable |
Disable a connector's cron |