Simple forgejo API client
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Heiko Schlittermann (ai) 36ecdd24df
All checks were successful
nagonag (Push) / nagonag (push) Successful in 1m1s
completion: complete --owner and issue search --repo ai:claude-opus-5-5
--owner (issue/pr list --global, issue search) offers the owners of all
repositories visible to the token; issue search --repo offers
owner/name, or bare names when --owner is given (case-insensitive).
The instance is the one the command would use: --instance, else the
repository host, else fj.default.

Both come from repos/search, the only suitable endpoint that works
without extra token scopes (/user/repos and /orgs/*/repos need
read:user or read:organization). The first page is fetched, then the
remaining pages concurrently, capped at 20 pages (1000 repositories).
Each request times out after 5s so a slow server cannot hang the
shell; api.Client gains SetTimeout for this.

Checked against forgejo.schlittermann.de: 29 owners, 358 repositories,
matching the raw API, in about 0.55s.
2026-09-26 11:08:37 +02:00
.forgejo/workflows fix runner names 2026-05-18 17:59:59 +02:00
.generated completion: complete --owner and issue search --repo ai:claude-opus-5-5 2026-09-26 11:08:37 +02:00
assets Move SVG banner to assets/ for proper rendering 2026-05-15 16:17:36 +02:00
docs completion: complete --owner and issue search --repo ai:claude-opus-5-5 2026-09-26 11:08:37 +02:00
internal completion: complete --owner and issue search --repo ai:claude-opus-5-5 2026-09-26 11:08:37 +02:00
.gitignore build: embed fj.1.gz and decompress on the fly 2026-05-18 22:16:08 +02:00
.gogogo.conf packaging: fix man page files 2026-05-18 21:56:21 +02:00
CLAUDE.md completion: complete --owner and issue search --repo ai:claude-opus-5-5 2026-09-26 11:08:37 +02:00
go.mod deps(master): update minor/patch dependencies 2026-05-18 16:02:02 +00:00
go.sum deps(master): update minor/patch dependencies 2026-05-18 16:02:02 +00:00
LICENSE Add tests, Apache-2.0 license, and README 2026-05-15 16:06:21 +02:00
main.go build: embed fj.1.gz and decompress on the fly 2026-05-18 22:16:08 +02:00
main_test.go add license files 2026-05-17 22:11:00 +02:00
Makefile add Makefile as convenience wrapper for go build / go generate 2026-05-18 08:31:48 +02:00
README.md docs, completion: document all commands, complete flag values and IDs ai:claude-opus-5-5 2026-09-26 01:19:33 +02:00
VERIFICATION_REPORT.md refactor: migrate parseIssueTemplate to IssueTemplateResult struct; wire assignees ai:claude-3.5-sonnet 2026-05-24 22:12:13 +02:00

fj — forgejo/gitea from the terminal

fj

A minimal Forgejo/Gitea CLI client. Manage issues and pull requests without leaving the terminal.

Features

  • Issue management: list, show, create, edit, close, delete, comments, labels, pins, reactions, deadlines, stopwatch and time tracking
  • Pull request management: list, show, create, edit, close
  • Instance-wide listings (--global) and full-text search across repositories
  • Auto-detects repo from git remote (SSH and HTTPS)
  • Credential resolution via git credential
  • Shell completion for commands, flags, and live repository data
  • Raw JSON output (--json) for scripting
  • Installs as git-fj for use as a git subcommand
  • Symlink as git-issues or git-prs for quick listing

Install

go install go.schlittermann.de/heiko/fj@latest

Place fj in $PATH. To use it as a git subcommand, add a symlink:

ln -s fj ~/bin/git-fj   # enables: git fj issue list

Usage

git fj issue list                     # open issues
git fj issue list --state closed      # closed issues
git fj issue show 42                  # issue details
git fj issue create --title "bug"     # new issue
git fj issue edit 42 --state closed   # close issue
git fj issue comment create 42 --body "fix"  # add comment
git fj issue search nagonag --type pulls     # full-text search, all repos

git fj pr list                        # open PRs
git fj pr show 7                      # PR details
git fj pr create --title "feat" --head dev
git fj pr edit 7 --state closed

git fj workflow init nagonag          # scaffold .forgejo/workflows/*.yaml
git fj workflow init nagonag --ref v1 # pin a source ref
git fj workflow init nagonag --force  # overwrite local edits

git fj issue list --json | jq '.[].title'

Instance-wide listings work inside any repository, or anywhere once an instance is registered:

fj login --alias fj https://git.example.org   # stores fj.fj.url, becomes fj.default
fj prs -g                                     # open PRs in all repositories
fj issues -g --assigned                       # issues assigned to me
fj issues -g --instance fj --owner heiko

fj login --with-token URL < token-file verifies a token and hands it to your git credential helper; tokens are never written to the git config.

Shell completion:

source <(fj completion bash)   # or zsh; fish: fj completion fish | source

Symlink shortcuts:

ln -s fj ~/bin/git-issues
ln -s fj ~/bin/git-prs
git issues              # same as: fj issue list
git prs                 # same as: fj pr list

Display the built-in manual page:

fj man

Configuration

fj reads configuration from git config:

git config fj.token <your-api-token>    # API token (optional if git credential works)
git config fj.remote upstream           # override remote detection (default: current branch remote, then origin)
git config --global fj.default fj       # instance for --global outside a repository (set by fj login)
git config --global fj.fj.url https://git.example.org   # instance alias (set by fj login)

Token resolution order:

  1. git config fj.token
  2. git credential fill for the remote host
  3. git credential fill after following redirects

Development

The man page source is docs/fj.1.md (pandoc Markdown). After editing it, regenerate and commit the derived files:

go generate ./...   # requires pandoc; writes .generated/fj.1{,.gz} and .generated/git-fj.1{,.gz}
git add docs/fj.1.md .generated/fj.1.gz .generated/git-fj.1.gz
git commit

Only the .gz files are committed; .generated/fj.1.gz is embedded in the binary. The uncompressed files are gitignored.

License

Apache-2.0. See LICENSE.