Skip to content
bzgPublic

About

GNAW is Not Another Workflow

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

94 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gnaw — GNAW is Not Another Workflow

https://img.shields.io/badge/versioning-intver.org-blue.svg?style=for-the-badge

gnaw (what you do to a bone) is a standalone Babashka script for browsing BONE reports. When fzf is available, gnaw lets you browse BONE reports interactively.

gnaw.png

Install

Assuming bbin is installed:

bbin install io.github.bzg/gnaw

Configure

Create ~/.config/gnaw/config.edn:

{:my-addresses ["you@example.com" "alias@example.com"]
 :text-browser "w3m"          ;; "w3m", "lynx" or "links"
 :diff-pager   "delta"        ;; "delta", "bat" or "diff-so-fancy"
 :sources      [{:urls ["https://example.com/reports/all.json"]
                 :name "Example ML"
                 :repo "~/src/example"}
                {:urls ["https://example.com/reports/all-open.json"
                        "https://example.com/reports/all-closed.json"]
                 :name "Another ML"}]}
  • :my-addresses — your email address(es), used by -m to filter reports involving you. Can be a single string or a vector of strings.
  • :text-browser — terminal browser for viewing reports on RET. When unset, gnaw probes for w3m, lynx, links, then falls back to xdg-open.
  • :diff-pager — pager for viewing patches on C-v. When unset, gnaw probes for delta, bat, then falls back to $PAGER or less.
  • :sources — vector of report sources. Each source is a map with:
    • :urls — a non-empty vector of URLs/paths to BONE reports.json files whose reports are merged into one source (e.g. an all-open.json and an all-closed.json).
    • :name — the source’s name. It is the unique key of a source: two sources may not share a :name, and it overrides the source of every report the source yields so the grouped files appear unified. --add-source fills it in from the sibling meta.json’s source field.
    • :repo — (optional) local git repository of the project, or a vector of them. gnaw only lists it with -l; gnaw.el applies the source’s patches there, so it must be a local directory, not a URL.
    • :letter — (optional) the letter identifying the source in gnaw.el’s report list, written by gnaw.el. gnaw ignores it.
  • :skip-columns — vector of column names to hide by default (e.g. ["priority" "owner"]). Columns: mark (alias !), type, source, priority (p), deadline (d), flags, replies (#), owner, author, date, att.
  • :report — configuration for gnaw report (see Triage report).

When adding an HTTP source, you may pass the full reports URL (.../reports/all.json), another report file (.../reports/all-open.json), or just the base URL (https://tracker.orgmode.org): gnaw resolves a bare base to reports/all.json and reads reports/meta.json to record :name.

gnaw shares ~/.config/gnaw/ with gnaw.el: the configuration, the local marks in state.edn and the cache.

Usage

gnaw [options]
gnaw report [options]
gnaw clear
gnaw update
gnaw todo
gnaw prune [--dry-run]

Options

OptionDescription
-f, --file FILERead reports from a JSON file
-u, --url URLFetch reports from a URL
-U, --urls-file FILEFetch and merge from URLs listed in FILE
-M, --my-addresses EMAILSYour email(s), comma-separated (overrides config)
-n, --source NAMEFilter by source name
-p, --min-priority NOnly show reports with priority >= N (1, 2 or 3)
-s, --min-score NOnly show reports with score >= N (0–7)
-S, --skip-columns COLSColumns to hide, comma-separated
-m, --mineShow only reports involving your address(es)
-T, --stickyShow only reports marked sticky
-A, --allShow all reports, including dismissed ones
-t, --test-configVerify ~/.config/gnaw/config.edn
-v, --versionShow the gnaw version
-h, --helpShow help
-Read JSON from stdin

Closed reports never appear in the interactive list; the related-reports view (C-/) and gnaw report still take them into account.

Local marks

Two local marks help triage: sticky (Alt-*, column ! shows *) keeps a report at hand, dismiss (Alt-Enter, column ! shows d) hides it from the next launches, until -A shows it again. The marks are mutually exclusive and stored with their timestamp in ~/.config/gnaw/state.edn, keyed by message-id; gnaw.el reads and sets the same marks.

CommandDescription
todoExport the sticky reports to ~/.config/gnaw/todo.org
pruneDrop the marks of reports no longer in any source
prune --dry-runList those marks without removing them

prune needs every source in the cache: run gnaw update first.

Triage report

gnaw report prints a text triage report to stdout. It accepts the same filtering options as interactive mode (-f, -u, -m, -n, etc.).

The report includes the following sections: overview, stale patches, stale bugs, active threads, expiring reports, recent reports, and owned reports. The overview counts open and closed reports; the other sections only list open ones.

The report can be configured in config.edn under the :report key:

{:report {:sections    ["overview" "stale-patches" "stale-bugs"
                        "active-threads" "expiring" "recent" "owned"]
          :stale-days  14   ;; threshold for "stale" (default: 14)
          :expiry-days 7    ;; threshold for "expiring" (default: 7)
          :recent-days 7    ;; threshold for "recent" (default: 7)
          :top-n       10}} ;; max items per section (default: 10)
  • :sections — list of sections to include in the report.
  • :stale-days — number of days after which an unacked report is considered stale.
  • :expiry-days — number of days ahead to look for expiring reports.
  • :recent-days — number of days to look back for recent reports.
  • :top-n — maximum number of items shown in each section but the overview.

Source management

CommandDescription
-a, --add-source URL_OR_PATHAdd a reports.json source
-r, --remove-source URL_OR_PATHRemove a source
-l, --list-sourcesList configured sources

Sources are stored in ~/.config/gnaw/config.edn under the :sources key.

--add-source accepts either a direct reports.json URL/path, which is added as-is with its name read from the sibling meta.json, or a tracker base URL (e.g. https://tracker.orgmode.org). Either way, the source is not added when no name can be read or another source already has it. Given a base URL, gnaw reads reports/meta.json for the source name and the list of available report files, then lets you pick which to add (via fzf, or a numbered prompt when fzf is absent). The chosen files are grouped into one named source:

{:urls ["https://tracker.orgmode.org/reports/all-open.json"
        "https://tracker.orgmode.org/reports/all-closed.json"]
 :name "Org mode ML"}

Cache management

CommandDescription
clearEmpty the cache, shared with gnaw.el
updateFetch/update reports from all sources

By default, gnaw reads cached reports if available. If no cache exists, it fetches from sources once and caches the result. Use gnaw update to refresh.

Interactive keys (fzf)

KeyAction
C-nMove to the next line
C-pMove to the previous line
RETView report in terminal browser
C-oOpen report in system browser
C-vView an attachment (patch, ics, text), fetched to cache
C-/Show related reports
C-sChange sort order
C-rFilter by report type
C-bFilter by source
C-tFilter by topic
C-xRemove current filters
C-uUpdate cache and reload
M-*Toggle the sticky mark
M-RETToggle the dismiss mark
C-hShow help

Columns: ! local mark (* sticky, d dismissed), P priority (A high, B medium, C low), D days until the deadline (negative when past), Flags (A)cked, (O)wned, then (C)anceled, (R)esolved, (E)xpired or (S)uperseded, # number of replies, Att + patches, @ events, # texts, ? awaiting a reply, ~ related reports.

Examples

Browse your reports from a local file:

gnaw -f reports.json -m

Browse all reports from a remote URL:

gnaw -u https://example.com/reports.json

Merge reports from multiple BONE instances:

gnaw -U my-urls.txt

The URLs file (-U) lists one URL per line; blank lines and # comments are ignored.

Add a source and browse:

gnaw -a https://example.com/reports.json

Update cached reports and browse only yours:

gnaw update
gnaw -m

Files

PathPurpose
~/.config/gnaw/config.ednUser configuration and sources
~/.config/gnaw/state.ednLocal sticky and dismiss marks
~/.config/gnaw/todo.orgSticky reports, by gnaw todo
~/.config/gnaw/cache/reports/Cached reports.json files
~/.config/gnaw/cache/patches/Cached patches
~/.config/gnaw/cache/events/Cached calendar files
~/.config/gnaw/cache/text/Cached text attachments

Contributing

You can also send me an email and support my work on liberapay.

Intentional Versioning

This project uses Intentional Versioning, here are the three audiences:

  • Users : end users who browse BONE reports with gnaw
  • Integrators : external packagers
  • Maintainers : maintainers of the codebase

Support the Clojure(script) ecosystem

If you like Clojure(script), please consider supporting maintainers by donating to clojuriststogether.org.

License

Copyright © 2026 Bastien Guerry

Distributed under the Eclipse Public License 2.0.

About

GNAW is Not Another Workflow

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages