- Go 99.7%
- Pkl 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
check / check (push) Successful in 42s
The list flags went to the API as written, so a misspelled --state or --sort answered the open list as if nothing had been asked, and the empty message then reported the word that was never a state as one: 'No bogus issues on tim/heimdarr'. state and sort are enums in the API's own document, so they are checked before the request, and page and limit are checked with them: a 0 was quietly dropped from the query, which is how --page 0 answered page 1 and a negative --limit answered the API's own small page. The empty answer read the state back out raw: --state all said 'No all issues on ...', naming all as if it were a state of its own. --web opens the list in the browser, which every other command here has and gh issue list has; the URL is spelled from the host and the path directly, so it opens with the API unreachable. |
||
| .forgejo/workflows | ||
| cmd/fj | ||
| forgejo | ||
| internal | ||
| .gitignore | ||
| .golangci.toml | ||
| AGENTS.md | ||
| go.mod | ||
| go.sum | ||
| hk.pkl | ||
| LICENSE.md | ||
| mise.toml | ||
| README.md | ||
[fj]
Quick Start:
fj auth add src.timharek.no
fj run ci.yml
fj run ci.yml dispatches a workflow file named in .forgejo/workflows/;
a repository without any has nothing to run.
A CLI for Forgejo, in the shape of the CLIs it replaces: gh for
GitHub and hut for Sourcehut. Commands work on the repository the
current directory belongs to, via the git remote called origin.
Install CLI
Using go:
go install src.timharek.no/tim/forgejo-cli/cmd/fj@latest
Using Homebrew
brew tap timharek/tap
brew trust timharek/tap
brew install timharek/tap/fj
Using pre-compiled binary
Select the version you want to install available releases and download
it and add it to your $PATH or something similar.
Example:
wget https://src.timharek.no/tim/forgejo-cli/releases/download/<release>/fj-<version>-linux-amd64.tar.gz
tar xf fj-<version>-linux-amd64.tar.gz
cd fj-<version>
cp fj /usr/local/bin
Setup
Create a token on your instance under Settings → Applications → Access
tokens, with at least repository and actions read access, then add
the host:
fj auth add src.timharek.no
The token is stored in your OS keyring; the host and login in
~/.config/forgejo-cli/config. List and manage them with fj auth list,
fj auth remove.
fj auth add prompts for anything missing. For scripts, pass --user and
--token, or skip storing a token at all by setting $FORGEJO_TOKEN.
Environment variables read:
$FORGEJO_TOKEN— API token, tried before the keyring$FORGEJO_HOST— host to use with--repowhen--hostisn't given$FORGEJO_CONFIG_DIR— where the config file lives ($XDG_CONFIG_HOME/forgejo-clior~/.config/forgejo-cliby default)
Usage
Every command works on the repository the current directory belongs to,
unless --repo owner/name says otherwise.
# Dispatch a workflow and watch it until it finishes
fj run ci.yml
fj run --ref staging ci.yml
fj run --no-watch ci.yml
# Follow the latest run of a workflow, then show the log
fj run watch ci.yml
fj run watch # the latest run of anything
fj run watch 12 # run number 12
fj run watch --web ci.yml # open the run in the browser instead
# Logs, listings, housekeeping — watch, logs, cancel and delete all take a
# workflow file name or a run number; list filters by workflow instead
fj run logs ci.yml --job check
fj run list [--workflow ci.yml] [--page N]
fj run cancel 12
fj run delete ci.yml
# Repositories
fj repo list # yours and the ones you collaborate on
fj repo list timharek # a user's or an organization's
fj repo view # details in the terminal
fj repo view --web # open in the browser
fj repo edit -d "a CLI" # change settings, only the flags given are changed
fj repo edit --visibility private
fj repo edit --enable-issues=false
# Pull requests
fj pr list # open ones, --state closed or all for the rest
fj pr status # the current branch's and yours, open only
fj pr view 3 # details in the terminal
fj pr view --web 3 # open in the browser
fj pr create # head is the current branch, base the default branch
fj pr create -t "a CLI" -b "why" --head feature --base main
fj pr edit 3 -t "a better title"
fj pr edit --reopen=false 3 # close it without merging
fj pr merge 3 # asks first; --style squash, --delete-branch
# Issues
fj issue list # open ones, --state closed or all for the rest
fj issue list -l bug -a tim --milestone v1
fj issue list --web # the list in the browser instead
fj issue view 3 # details in the terminal
fj issue view --comments 3 # with the comments under it
fj issue view --web 3 # open in the browser
fj issue create -t "a CLI" -b "why" -l bug -a tim # body from stdin when piped
fj issue edit 3 -t "a better title"
fj issue edit 3 --add-label docs --remove-label bug
fj issue close 3 -c "shipped in v1"
fj issue reopen 3
fj issue comment 3 -b "on it"
fj issue delete 3 # asks first; --force
# Secrets, on the repository or, with --org, on an organization
fj secret list
fj secret set DEPLOY_KEY # hidden prompt, or piped in
fj secret set NPM_TOKEN --body "$NPM_TOKEN"
fj secret set -o timharek ORG_TOKEN --body "$TOKEN"
fj secret delete DEPLOY_KEY
fj secret set reads the value from --body, from stdin when it is piped,
or from a hidden prompt. Names are checked here, so a name the instance
would refuse is a sentence rather than a 400.
fj run picks the job to show the log of: the one job when the run has
exactly one, otherwise you are asked which. With no workflow given and
exactly one in the repository, that one is dispatched. Shell completion is
generated by fj completion bash|zsh|fish|powershell.
fj pr create takes the head branch from the checkout and the base branch
from the repository, so fj pr create -t "a title" is usually all of it.
Scripting
Global flags: --repo owner/name (or -R), --host, --remote,
--config, --debug.
--json prints machine-readable output: repo list, repo view,
repo edit, pr list, pr status, pr view, pr create, pr edit, pr merge,
auth list, secret list and the run subcommands print the API objects;
run watch prints a status snapshot after each poll and the final run.
cancel, delete, merge, secret delete and auth remove ask for
confirmation unless --force is given. Without a terminal there is nobody
to ask, so they fail instead of guessing — a script that means it passes
--force.
Why
Forgejo ships forgejo-cli, whose commands are shaped
differently from the CLIs most people know. fj follows gh and hut
instead: dispatch with run, follow with watch, open with
repo view --web or pr view --web.
License
MIT, see LICENSE.md.