Cheatsheet
Geri
The hunter — outdated dependencies, security advisories, and drift, run down in one sweep.
View on GitHubQuick reference for every command, option, and behavior. geri is the hunter of your GitHub
estate — it sweeps every repo under the estate root for security and freshness risk (open Dependabot
alerts, outdated deps, unpinned/outdated Actions) and reports the estate-wide picture in one pass.
Everything is derived live from the GitHub API via gh (plus a bounded local scan) — no database, no
cache, no stored state.
For the narrative version see the README; for per-command detail in the terminal, run
geri <command> help.
At a glance
| Command | Aliases | What it does | Options |
|---|---|---|---|
alerts | (none) | Open Dependabot security alerts, estate-wide, most-severe first | [repo], --flat |
deps | (none) | Outdated dependencies: unmonitored manifests + open Dependabot update PRs | [repo] |
actions | (none) | Third-party Actions pinned to a moving tag / behind latest | [repo] |
hunt | (none) | Combined summary — alerts · deps · actions, per repo | --md |
init | (none) | Write a geri config with detected defaults | --force |
help | -h, --help | The command menu |
- geri is entirely read-only. It reports risk — where you’re exposed, what’s behind, what’s
unpinned — and never touches a repo, its settings, or its Actions. There is no
--apply; fixing is Dependabot’s job (or a later geri phase). Its sibling freki is the one with teeth. - Everything is estate-scoped: one sweep across every repo under
$GERI_ROOT, minus exemptions. Pass a[repo]name toalerts/deps/actionsto narrow it to a single repo. - Running
geriwith no command prints the menu (same asgeri help).
Requirements & global behavior
- Requires
bash,git,gh(authenticated), andjq— all four. Unlike a local-only tool, every command reaches GitHub throughgh; there’s no offline fallback.depsandactionsadd a bounded local scan (manifests / workflow files) on top of one network call. - Alerts need security-read access, and degrade gracefully.
alerts(and the alerts slice ofhunt) callgh api .../dependabot/alertsper repo. When that doesn’t come back as a JSON array — Dependabot alerts disabled, or you lack security-read on the repo — geri counts that repo separately as “checked without Dependabot alerts enabled” rather than erroring or crashing. Disabled and no-access fold into the same tally; enable it in the repo’s Settings → Code security to have geri cover it.huntsimply skips such repos silently. - Config model — settings resolve env
GERI_*→ config file → smart default. The file is${XDG_CONFIG_HOME:-~/.config}/geri/config(override withGERI_CONFIG); rungeri initto write one. Keys:GERI_ROOT(default~/github-repos),GERI_OWNER(default yourghlogin, resolved lazily),GERI_FAMILY(repos to exclude),GERI_CONVENTIONS(dir holdingexemptions.json). If~/.config/huginn/configexists and the matchingGERI_*value is unset, geri falls back to huginn’sHUGINN_ROOT/HUGINN_OWNER/HUGINN_FAMILY/HUGINN_CONVENTIONS— a huginn user gets a working geri with zero setup. - Exemptions — the estate is every directory under
$GERI_ROOTcontaining a.git. A repo exempt from huginn is exempt from the hunt too: geri mergesexemptions.json(in the conventions dir) with$GERI_FAMILY/$HUGINN_FAMILYand skips those repos everywhere. Same list the ravens skip. NO_COLOR— set it (NO_COLOR=1 geri …) to disable color. Output is also automatically plain when piped or redirected (not a TTY).- Two-level help —
geri helpfor the menu,geri <command> help(or-h/--help) for one command. - Read-only, no
--json. Output is terminal by default; onlyhuntoffers a machine-portable form,--md(a Markdown briefing). There is no JSON emitter in v0.1. - Exit codes —
0on success;1on an unknown command, or when no GitHub owner can be resolved (not configured andgh api userfails). An unknown per-command flag is warned and ignored (ignoring unknown option: …), not fatal.
Hunt
alerts
Open Dependabot security alerts across the estate, most-severe first. Grouped by repo (worst repo
first) by default, or one flat severity-sorted list with --flat. One gh api .../dependabot/alerts
call per repo (excluding exempt repos), the same cost class as huginn doctor. The headline view —
where am I exposed, everywhere, right now.
Severity order: critical · high · medium · low.
geri alerts # every repo, grouped by repo (worst first)
geri alerts --flat # one severity-sorted list across the whole estate
geri alerts day-one # just one repo
geri alerts day-one --flat # a single repo, flat list
| Option | Effect |
|---|---|
[repo] | Check a single repo instead of the whole estate |
--flat | One severity-sorted list across the estate (worst repo first), instead of grouped by repo |
A repo with Dependabot alerts disabled (or that you can’t read) is tallied as “checked without Dependabot alerts enabled” and reported in the footer — counted, never treated as an error.
deps
Outdated dependencies across the estate, two signals:
- unmonitored — a repo carries a manifest (
package.json,go.mod,Cargo.toml, …) but has no.github/dependabot.ymlwatching it; its staleness is invisible until one is added. (Bounded local scan: depth 2, skipsnode_modules/vendor/dist/build.) - open update PRs — Dependabot’s own open version-update PRs, oldest first. One
gh search prscall covers the whole estate, the same one-call pattern ashuginn prs.
geri deps # the whole estate
geri deps huginn # just one repo
| Option | Effect |
|---|---|
[repo] | Check a single repo instead of the whole estate |
actions
Third-party GitHub Actions pinned to a moving tag (e.g. @v4) instead of a commit SHA, or pinned
to a tag that’s behind the action’s latest release — the supply-chain-hygiene gap
repo-conventions §3 calls for (pin actions to a SHA). Your own (brett-buskirk/*) actions are
excluded; the guidance is scoped to third parties.
A bounded local scan of each repo’s .github/workflows/*.yml for uses: lines, then one
gh api .../releases/latest call per unique action (deduped across the estate) to tell a
merely-unpinned action apart from an actually-outdated one. A ref that isn’t version-shaped (@main,
@beta) is flagged as tracking a branch/channel — arguably the riskiest kind, since it can change
without notice (shown in red, sorted to the top).
geri actions # the whole estate
geri actions heimdall # just one repo
| Option | Effect |
|---|---|
[repo] | Check a single repo instead of the whole estate |
hunt
The combined what needs running down summary — alerts, deps, and actions, per repo, with an estate
headline (N alerts · M outdated dep signals · K unpinned actions). Lighter than running all three
commands: it skips the outdated-vs-latest lookup geri actions does (it just counts unpinned usages) —
run geri actions for that detail. The most expensive geri command: a full sweep (one alerts call per
repo, one PR search, a local workflow scan).
--md emits a clean Markdown briefing to stdout instead of the terminal view — redirect it to a file
for something shareable, the way muninn digest --md works.
geri hunt # terminal summary
geri hunt --md # Markdown briefing to stdout
geri hunt --md > hunt.md # …saved as a shareable file
| Option | Effect |
|---|---|
--md | Emit a Markdown briefing to stdout instead of the terminal view |
Configure
init
Write a config file (${XDG_CONFIG_HOME:-~/.config}/geri/config) with detected defaults — your GitHub
login and estate root — then edit it. Won’t clobber an existing config unless you pass --force.
Config keys (an env GERI_* var overrides the file): GERI_ROOT · GERI_OWNER · GERI_FAMILY ·
GERI_CONVENTIONS. If ~/.config/huginn/config exists and a GERI_* value is unset, geri falls back
to huginn’s settings, so this file only needs the keys you want to diverge on.
geri init # write a config (no-op if one already exists)
geri init --force # overwrite an existing config
| Option | Effect |
|---|---|
--force | Overwrite an existing config file instead of leaving it be |
help
geri help # the command menu
geri -h # same
geri --help # same
geri <command> help # detail for one command (e.g. geri alerts help)
Running geri with no arguments prints the menu.
Recipes
# Where am I exposed, everywhere, right now?
geri alerts
# One severity-sorted list across the estate — worst first
geri alerts --flat
# Alerts for just one repo (e.g. the one with a live Dependabot alert)
geri alerts day-one
# What's behind everywhere — unwatched manifests + open update PRs
geri deps
# Which third-party actions aren't SHA-pinned (or are outdated)?
geri actions
# The full picture in one sweep — alerts · deps · actions
geri hunt
# A shareable Markdown briefing to hand off or commit
geri hunt --md > hunt-$(date +%F).md
# First-run setup — write a config with detected defaults
geri init
# Plain output for a log or pipe (no color)
NO_COLOR=1 geri hunt