Skip to content

Linux

One static binary, CGO_ENABLED=0, so there is no C library to install and no distribution to match. A release archive and a PATH entry is the whole install; everything below that is about doing it deliberately.

Release archives are named ghchronicle_<version>_linux_<arch>.tar.gz, with <arch> either amd64 or arm64. uname -m answers which.

uname -m reportsThe archive to take
x86_64linux_amd64
aarch64linux_arm64
Terminal window
VERSION=1.0.0
arch=$(uname -m); case "$arch" in x86_64) arch=amd64 ;; aarch64) arch=arm64 ;; esac
base=https://github.com/jmrplens/ghchronicle/releases/download/v$VERSION
curl -fsSLO "$base/ghchronicle_${VERSION}_linux_${arch}.tar.gz"

Two files are published beside the archives: checksums.txt, which holds the SHA-256 of every archive, and checksums.txt.sigstore.json, which is a signature over that file. So the chain is one signature and a digest: verify the file, then verify the archive against the file.

  1. Take the checksum file and its signature.

    Terminal window
    curl -fsSLO "$base/checksums.txt"
    curl -fsSLO "$base/checksums.txt.sigstore.json"
  2. Check the archive against it. --ignore-missing is what lets one line of a twelve-line file be checked without the other eleven archives being present.

    Terminal window
    sha256sum --ignore-missing -c checksums.txt
    ghchronicle_1.0.0_linux_amd64.tar.gz: OK
  3. Check the checksum file itself, if you have cosign.

    Terminal window
    cosign verify-blob \
    --certificate-identity-regexp 'https://github.com/jmrplens/ghchronicle/.github/workflows/release.yml@refs/tags/.*' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com \
    --bundle checksums.txt.sigstore.json \
    checksums.txt
    Verified OK

The signing is keyless: there is no public key to fetch and no private key for anyone to lose, because the identity being verified is the workflow that ran, recorded in a public transparency log. That is what the two --certificate flags say, and why they are not optional: without them cosign would confirm that somebody signed the file, which is not the question.

The archive holds three files and no directory, so extract it somewhere you meant to.

  • Directoryghchronicle_1.0.0_linux_amd64.tar.gz
    • ghchronicle the binary
    • LICENSE
    • README.md
Terminal window
tar -xzf ghchronicle_1.0.0_linux_amd64.tar.gz ghchronicle
sudo install -m 755 ghchronicle /usr/local/bin/
ghchronicle -version
ghchronicle 1.0.0 (commit 4e5dfc2, built 2026-09-14T23:04:02Z)

The binary needs a configuration file and a token, and the quickstart writes both in six steps. With those in place:

Terminal window
ghchronicle -config config.yaml -list # what would be collected
ghchronicle -config config.yaml -once # one sweep, then exit

systemd is the arrangement this documentation treats as the default on Linux, and the unit there is hardened rather than minimal, because this is very likely the only process on the host holding a GitHub token with read access to every repository of an account.

A scheduler works too: cron with -once is a single line, at the cost of giving every family the same cadence.

Go 1.27.1 or newer is what the module declares. Nothing else is needed: the build sets CGO_ENABLED=0, so there is no compiler and no header package to find.

Terminal window
go install github.com/jmrplens/ghchronicle/cmd/ghchronicle@latest

Lands in $(go env GOPATH)/bin, which is ~/go/bin unless you moved it, and that directory has to be on your PATH.

A binary built this way reports its version but not its commit or its build date:

ghchronicle 1.0.0 (commit unknown, built unknown)

The version comes from the VERSION file the module embeds; the other two are stamped by the release build and by nothing else, and a module downloaded through the proxy carries no checkout to read them from.

The collector looks for a configuration file in no particular place: -config defaults to config.yaml relative to the working directory, and there is no search path behind it. So the path is a decision you make once and then pass on every invocation. What the rest of this documentation assumes:

FilePathMode
Configuration/etc/ghchronicle/config.yamlworld readable, no secrets
Tokens/etc/ghchronicle/ghchronicle.env600
State and ledger/var/lib/ghchronicle/written by the service user

state_file has a default of its own, ghchronicle-state.json in the working directory, with the write ledger beside it as ghchronicle-state-written.bin. That default is fine for a first run in a directory you made, and wrong for a service, whose working directory is not something to rely on. Set it.