Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
#+title: gnaw — GNAW is Not Another Workflow #+author: Bastien Guerry [[https://intver.org/][https://img.shields.io/badge/versioning-intver.org-blue.svg?style=for-the-badge]] *gnaw* (what you do to a bone) is a standalone [[https://github.com/babashka/babashka][Babashka]] script for browsing [[https://codeberg.org/bzg/bone][BONE]] reports. When [[https://github.com/junegunn/fzf][fzf]] is available, gnaw lets you browse BONE reports interactively. [[file:gnaw.png]] * Install Assuming [[https://github.com/babashka/bbin][bbin]] is installed: : bbin install io.github.bzg/gnaw * Configure Create =~/.config/gnaw/config.edn=: #+begin_src clojure {: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 "https://example.com/repo"} {:urls ["https://example.com/reports/all-open.json" "https://example.com/reports/all-closed.json"] :name "Another ML"}]} #+end_src - =: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) public URL or local path of the associated code repository. 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=. - =:skip-columns= — vector of column names to hide by default (e.g. =["priority" "score"]=). - =:report= — configuration for =gnaw report= (see [[*Triage report][Triage report]]). * Usage : gnaw [options] : gnaw report [options] : gnaw clear : gnaw update ** Options | Option | Description | |---------------------------+---------------------------------------------------| | =-f=, =--file FILE= | Read reports from a JSON file | | =-u=, =--url URL= | Fetch reports from a URL | | =-U=, =--urls-file FILE= | Fetch and merge from URLs listed in FILE | | =-M=, =--my-addresses EMAILS= | Your email(s), comma-separated (overrides config) | | =-n=, =--source NAME= | Filter by source name | | =-p=, =--min-priority N= | Only show reports with priority >= N (1, 2 or 3) | | =-s=, =--min-score N= | Only show reports with score >= N (0–7) | | =-S=, =--skip-columns COLS= | Columns to hide, comma-separated | | =-m=, =--mine= | Show only reports involving your address(es) | | =-c=, =--closed= | Include closed reports | | =-= | Read JSON from stdin | ** Triage report =gnaw report= prints a text triage report to stdout. It accepts the same filtering options as interactive mode (=-f=, =-u=, =-m=, =-c=, etc.). The report includes the following sections: overview, stale patches, stale bugs, active threads, recent reports, and owned reports. The report can be configured in =config.edn= under the =:report= key: #+begin_src clojure {:report {:sections ["overview" "stale-patches" "stale-bugs" "active-threads" "recent" "owned"] :stale-days 14 ;; threshold for "stale" (default: 14) :recent-days 7 ;; threshold for "recent" (default: 7) :top-n 10}} ;; max items per section (default: 10) #+end_src - =:sections= — list of sections to include in the report. - =:stale-days= — number of days after which a report is considered stale. - =:recent-days= — number of days to look back for recent reports. - =:top-n= — maximum number of items shown in stale and active-threads sections (=recent= and =owned= are not capped). ** Source management | Command | Description | |---------------------------------+---------------------------| | =-a=, =--add-source URL_OR_PATH= | Add a reports.json source | | =-r=, =--remove-source URL_OR_PATH= | Remove a source | | =-l=, =--list-sources= | List 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, or a tracker /base URL/ (e.g. =https://tracker.orgmode.org=). 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: #+begin_src clojure {:urls ["https://tracker.orgmode.org/reports/all-open.json" "https://tracker.orgmode.org/reports/all-closed.json"] :name "Org mode ML"} #+end_src ** Cache management | Command | Description | |---------+---------------------------------------| | =clear= | Empty the cache | | =update= | Fetch/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) | Key | Action | |-----+---------------------------------| | =C-n= | Move to the next line | | =C-p= | Move to the previous line | | =RET= | View report in terminal browser | | =C-o= | Open report in system browser | | =C-v= | View patch (fetched to cache) | | =C-s= | Change sort order | | =C-r= | Filter by report type | | =C-b= | Filter by source | | =C-t= | Filter by topic | | =C-u= | Update cache and reload | | =C-h= | Show help | | C-x | Remove current filters | * 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 | Path | Purpose | |-------------------------------+--------------------------------| | =~/.config/gnaw/config.edn= | User configuration and sources | | =~/.config/gnaw/cache/patches/= | Cached patches | | =~/.config/gnaw/cache/reports/= | Cached reports.json files | * Contributing - Send a [[mailto:~bzg/boneyard@lists.sr.ht][bug report]] with =[BUG] gnaw: <SHORT EXPLICIT BUG DESCRIPTION>= - Send a [[mailto:~bzg/boneyard@lists.sr.ht][patch]] with =[PATCH] gnaw: <COMMIT SUMMARY>= - Send a [[mailto:~bzg/boneyard@lists.sr.ht][feature request]] with =[FR] gnaw: <FEATURE REQUEST>= - Share any [[mailto:~bzg/boneyard@lists.sr.ht][other question or idea]] You can also [[mailto:bzg@bzg.fr][send me an email]] and support my work on [[https://liberapay.com/bzg/][liberapay]]. * Intentional Versioning This project uses [[https://intver.org][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 [[https://clojuriststogether.org][clojuriststogether.org]]. * License Copyright © 2026 Bastien Guerry Distributed under the [[https://www.eclipse.org/legal/epl-2.0/][Eclipse Public License 2.0]].