- Clojure 100%
| docs | ||
| LICENSES | ||
| resources | ||
| scripts | ||
| src/bark_ingest | ||
| test | ||
| .gitignore | ||
| bb.edn | ||
| config.edn.example | ||
| deps.edn | ||
| README.org | ||
🐕 BARK — Bug And Report Keeper
BARK is an email-driven report tracker - see the rationale.
BARK monitors a single IMAP mailbox, classifies incoming emails into sources by header matching, detects report types from subject tags, applies state triggers from email body, and manages roles per source.
To browse BARK reports from the command line, you can use bone.
User documentation
As a Bark user, you want to read the HOWTO.
How it works
- bark-ingest — Connects to IMAP via IDLE, stores emails in the db.
- bark-digest — Scans new emails and creates/updates reports/roles in the db.
- bark-export — Exports all reports as JSON, RSS, or Org.
- bark-html — Generates a static HTML page embedding report data (via
bb export html). - bark-notify — Sends notification emails to admin/maintainers.
Dependencies
- Babashka (bb)
- Java 17+ (for bark-ingest)
- Datalevin (pod for bb, library for JVM)
Quick start
# 1. Copy and edit config
cp config.edn.example config.edn
# 2. Start ingesting emails
clj -M:run
# 3. Digest new emails into reports
bb digest # incremental
bb digest --all # rescan everything
# 4. Export reports
bb export # → public/reports.json
bb export rss # → public/reports.rss
bb export org # → public/reports.org
bb export html # → public/index.html
bb export stats # → public/stats.json
bb export all # → all of the above
# 5. Test SMTP configuration
bb test-smtp --dry-run
# 6. Send notification emails
bb notify # send due notifications
bb notify --dry-run --debug # preview without sending
bb tasks
bb digest [--all] Digest emails into reports
bb export [json|rss|org|html|stats|all] Export all reports (default: json)
[-n source] [-p 1|2|3] [-s 1-7] Filter by source, priority, status
bb notify [--dry-run] [--force] [--debug] Send notification emails
bb test-config [path] Validate config.edn
bb test-digest Run bark-digest integration tests
bb test-smtp [--to addr] [--dry-run] Test SMTP configuration
bb clean Remove all files in public/
The notify command also accepts --force (ignore interval, send now)
and --debug (print filtering diagnostics).
Config
See config.edn.example. The configuration has three main sections:
IMAP connection (:imap)
Single IMAP connection shared by all sources.
| Field | Required | Description |
|---|---|---|
:host |
yes | IMAP server hostname |
:user |
yes | IMAP login username |
:password |
* | IMAP password (* or :oauth2-token) |
:oauth2-token |
* | OAuth2 token (* or :password) |
:folder |
yes | IMAP folder (usually "INBOX") |
Sources (:sources)
Each source classifies incoming emails by header matching. Sources are
checked in order; the first match wins. A source without :match acts
as a catch-all.
| Field | Required | Description |
|---|---|---|
:name |
yes | Unique source identifier |
:match |
no | Header matching rules (see below) |
:mailing-list-email |
no | Associated mailing list address |
:admin |
no | Admin for this source (fallback: global) |
:triggers |
no | Body-trigger word overrides (per action) |
:labels |
no | Report label overrides (per report type) |
Match rules (all optional, all must match if present):
| Key | Matches against | Example |
|---|---|---|
:list-id |
List-Id header |
"bugs.example.org" |
:delivered-to |
Delivered-To |
"bugs@example.com" |
:to |
To header |
"inbox@example.com" |
Example config
{:admin "admin@example.com"
:imap {:host "imap.example.com" :port 993 :ssl true
:user "imap-login@example.com" :password "secret"
:folder "INBOX"}
:sources [{:name "public-list"
:match {:list-id "bugs.example.org"}
:mailing-list-email "bugs@example.org"
:admin "lead@example.org"}
{:name "private"
:match {:delivered-to "private@example.com"}}
{:name "direct"}]
:db {:path "data/bark-db"}
:ingest {:initial-fetch 50}
:notifications {:enabled true
:smtp {:host "smtp.example.com" :port 587 :tls true
:user "notify@example.com" :password "secret"
:from "bark@example.com"}}}
Report labels (:labels)
Controls which subject tags are recognised per report type. Can be set globally at the top level or per source (per-source takes precedence). Only the types you specify are overridden; others keep their defaults.
Default tags:
| Type | Default tags |
|---|---|
:bug |
BUG |
:patch |
PATCH |
:request |
POLL FR TODO |
:announcement |
ANN ANNOUNCEMENT |
:release |
REL RELEASE |
:change |
CHG CHANGE |
Example (global, in config.edn):
:labels {:bug ["BUG" "DEFECT"]
:request ["POLL" "FR" "TODO" "RFE"]}
Per-source (inside a source map):
{:name "my-list"
:labels {:announcement ["ANN" "NEWS"]}}
Notifications (:notifications)
Optional. When absent or {:enabled false}, bb notify exits
immediately.
| Field | Required | Description |
|---|---|---|
:enabled |
yes | Global kill switch (true=/=false) |
:smtp |
yes | SMTP connection settings (see below) |
SMTP fields:
| Field | Required | Description |
|---|---|---|
:host |
yes | SMTP server hostname |
:port |
yes | SMTP port (usually 587) |
:tls |
no | Enable STARTTLS (true) |
:user |
yes | SMTP login username |
:password |
yes | SMTP password |
:from |
yes | Sender address for emails |
Use bb test-smtp --dry-run to validate the configuration without
sending, or bb test-smtp to send a test email to the global admin.
License
Copyright © 2026 Bastien Guerry
Distributed under the Eclipse Public License 2.0.