gh-not

module
v0.6.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2026 License: MIT

README ¶

gh-not 🔕

GitHub rule-based notifications management

Go Reference CI CodeQL

[!IMPORTANT] The project is mostly "done" at this point. I won't be adding any new features.

I will accept PRs/issues for bug/improvements.

demo.gif

Install

  • Install via gh (preferred method):

    gh extension install nobe4/gh-not
    

    It is then used with gh not.

  • Download a binary from the release page.

  • Build from sources

    go generate ./...
    go build ./cmd/gh-not
    

    See version.go for custom build info.

Getting started

Run the following commands to get started and see the available commands and options:

gh-not --help
gh-not config --init
gh-not sync
gh-not --filter '.author.login | contains("4")'
gh-not --repl
...

How it works

gh-not fetches the notifications from GitHub and saves them in a local cache.

The synchronization between local and remote notifications is described in sync.go.

The sync command applies the rules to the notifications and performs the specified actions. It's recommended to run this regularly, see this section.

The other commands are used to interact with the local cache. It uses gh api-equivalent to modify the notifications on GitHub's side.

Authentication

gh-not uses gh's built-in authentication, meaning that if gh works, gh-not should work.

If you want to use a specific PAT, you can do so with the environment variable GH_TOKEN. The PAT requires the scopes: notifications, and repo.

E.g.:

# gh's authentication for github.com
gh-not ...

# Using a PAT for github.com.
GH_TOKEN=XXX gh-not ...

gh-not also respects GH_HOST and GH_ENTERPRISE_TOKEN if you need to use a non-github.com host.

E.g.:

# gh's authentication for ghe.io
GH_HOST=ghe.io gh-not ...

# Using a PAT for ghe.io
GH_HOST=ghe.io GH_ENTERPRISE_TOKEN=XXX gh-not ...

See the gh environment documentation.

[!IMPORTANT] If you plan on using gh-not with more than one host, you might want to create a separate cache for it. See cache.

Configuration

Cache

The cache is where the notifications are locally stored.

It contains 2 fields:

  • path: the path to the JSON file.

  • TTLInHours: how long before the cache needs to be refreshed.

If you use multiple hosts, you might want to have separate configurations and caches to prevent overrides. Create one config file per host you want to use and point the cache's path to a different file.

E.g.

  • config.github.yaml

    cache:
      path: cache.github.json
    ...
    

    Use it with gh-not --config config.github.yaml.

  • config.gheio.yaml

    cache:
      path: cache.gheio.json
    ...
    

    Use it with gh-not --config config.gheio.yaml.

Rules

The configuration file contains the rules to apply to the notifications. Each rule contains three fields and must contain an action and at least one filter.

  • name: the display name

  • action: the action to perform on the notification

    The current list of action is found in actions.go.

  • filters: a list of jq filters[^gojq] to filter notifications with.

    Each filter is inserted into the following pattern: .[] | select(%s).

    Each filter in the list is run one after the other, making it similar to joining them with and.

    It means that if you want to specify conditions with or, you need to write them directly in the filter.

    E.g.

    rules:
      - filters:
          - (.author.login == "dependabot[bot]") or (.author.login == "nobe4")
          - .repository.full_name == "nobe4/gh-not"
    

    Filters like:

    jq '.[] | select((.author.login == "dependabot[bot]") or (.author.login == "nobe4"))' | jq '.[] | select(.repository.full_name == "nobe4/gh-not")'
    

    See more at config.go and rule.go.

Examples
- name: mark closed dependabot PRs as done
  filters:
    - .author.login == "dependabot[bot]"
    - .subject.state == "closed"
  action: done
- name: ignore a specific repo
  filters:
    - .repository.name == "greg-ci-tests"
  action: done
- name: close read notifications
  filters:
    - .unread == false
  action: done
- name: mark notifications of PRs closed over a week ago as read
  filters:
    - .subject.state == "closed"
    - .updated_at | fromdate < now - 604800
  action: read
- name: close read notifications older than 2 weeks
  filters:
    - .unread == false    
    - .updated_at | fromdate < now - 1209600
  action: done
- name: mark pull requests merged by yourself as read
  filters:    
    - .merged_by.login == "Tethik"
    - .subject.state == "closed"
  action: read

Automatic fetching

To automatically fetch new notifications and apply the rules, it is recommended to set up an automated process to run gh-not sync regularly.

E.g.

  • cron

    0 * * * *  gh-not sync --config=/path/to/config.yaml --verbosity=4 >> /tmp/gh-not-sync.out 2>> /tmp/gh-not-sync.err
    
  • launchd (macOS)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <key>EnvironmentVariables</key>
        <dict>
          <key>PATH</key>
          <string>/opt/homebrew/bin/:$PATH</string>
        </dict>
    
        <key>Label</key>
        <string>launched.gh-not-sync.hourly</string>
    
        <key>ProgramArguments</key>
        <array>
          <string>sh</string>
          <string>-c</string>
          <string>gh-not sync --config=/path/to/config.yaml --verbosity=4</string>
        </array>
    
        <key>StandardErrorPath</key>
        <string>/tmp/gh-not-sync.err</string>
        <key>StandardOutPath</key>
        <string>/tmp/gh-not-sync.out</string>
    
        <key>StartInterval</key>
        <integer>3600</integer>
      </dict>
    </plist>
    

    It is recommended to use https://launched.zerowidth.com/ for generating such Plist.

[^gojq]: Technically, gojq is used.

Directories ¶

Path Synopsis
cmd
gh-not command
internal
actions/assign
Package assign implements an [actions.Runner] that assigns the subject of a notification.
Package assign implements an [actions.Runner] that assigns the subject of a notification.
actions/debug
Package debug implements an [actions.Runner] that prints a notification with a DEBUG prefix.
Package debug implements an [actions.Runner] that prints a notification with a DEBUG prefix.
actions/done
Package done implements an [actions.Runner] that marks a notification as done.
Package done implements an [actions.Runner] that marks a notification as done.
actions/hide
Package hide implements an [actions.Runner] that hides a notification.
Package hide implements an [actions.Runner] that hides a notification.
actions/json
Package json implements an [actions.Runner] that prints a notification in JSON.
Package json implements an [actions.Runner] that prints a notification in JSON.
actions/open
Package open implements an [actions.Runner] that opens a notification in the browser.
Package open implements an [actions.Runner] that opens a notification in the browser.
actions/pass
Package pass implements an [actions.Runner] that does nothing.
Package pass implements an [actions.Runner] that does nothing.
actions/print
Package print implements an [actions.Runner] that prints a notification.
Package print implements an [actions.Runner] that prints a notification.
actions/read
Package read implements an [actions.Runner] that marks a notification as read.
Package read implements an [actions.Runner] that marks a notification as read.
actions/tag
Package tag implements an [actions.Runner] that manages tags in a notification.
Package tag implements an [actions.Runner] that manages tags in a notification.
api
cache
Package cache provides a simple file-based cache implementation that fulfills the RefreshReadWriter interface.
Package cache provides a simple file-based cache implementation that fulfills the RefreshReadWriter interface.
cmd
config
Package config provides a way to load the configuration from a file.
Package config provides a way to load the configuration from a file.
gh
Package gh interact with GitHub's api, wrapper around cli/go-gh client object.
Package gh interact with GitHub's api, wrapper around cli/go-gh client object.
jq

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL