Bug And Report Keeper
Find a file
2026-03-07 09:07:29 +01:00
docs doc: Fix minor inconsistencies 2026-03-06 22:01:56 +01:00
LICENSES Initial commit 2026-03-01 10:59:23 +01:00
resources feat: Rename bark-egest.clj to bark-export.clj 2026-03-05 07:32:52 +01:00
scripts fix: Remove left-over println 2026-03-07 09:07:29 +01:00
src/bark_ingest feat: Add :archive-format-string to the config 2026-03-07 01:24:16 +01:00
test fix: Bump to datalevin 0.10.7 2026-03-06 23:10:54 +01:00
.gitignore chore: Refactoring 2026-03-06 18:03:17 +01:00
bb.edn feat: Add :archive-format-string to the config 2026-03-07 01:24:16 +01:00
config.edn.example feat: Add :archive-format-string to the config 2026-03-07 01:24:16 +01:00
deps.edn fix: Bump to datalevin 0.10.7 2026-03-06 23:10:54 +01:00
README.org doc: Fix minor inconsistencies 2026-03-06 22:01:56 +01:00

🐕 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.