2026-05-13 14:56:28 +00:00
|
|
|
# fj
|
|
|
|
|
|
|
|
|
|
A command-line tool for [Forgejo](https://forgejo.org) instances, in the spirit of GitHub's `gh`.
|
|
|
|
|
|
|
|
|
|
Multi-host from day one. Tokens are stored in your OS keychain.
|
|
|
|
|
|
|
|
|
|
## Install
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo install --path .
|
2026-05-13 15:42:34 +00:00
|
|
|
# or
|
|
|
|
|
cargo build --release && cp target/release/fj ~/.local/bin/fj
|
2026-05-13 14:56:28 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Quick start
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
fj auth login # add a host and token
|
|
|
|
|
fj auth status # show signed-in hosts
|
2026-05-13 15:42:34 +00:00
|
|
|
fj repo list # repos you own
|
2026-05-13 14:56:28 +00:00
|
|
|
fj repo view owner/name # repo overview
|
|
|
|
|
fj issue list -R owner/name # issues
|
|
|
|
|
fj pr list -R owner/name --state open # pull requests
|
2026-05-13 15:42:34 +00:00
|
|
|
fj api /repos/search -X GET -f q=foo # raw API escape hatch
|
2026-05-13 14:56:28 +00:00
|
|
|
```
|
|
|
|
|
|
2026-05-13 15:42:34 +00:00
|
|
|
`-R/--repo` is optional inside a git clone. fj detects the upstream from
|
|
|
|
|
`upstream`, then `origin`, then any other remote.
|
2026-05-13 14:56:28 +00:00
|
|
|
|
|
|
|
|
## Commands
|
|
|
|
|
|
2026-05-13 15:42:34 +00:00
|
|
|
| Group | Common operations |
|
|
|
|
|
| ---------- | --------------------------------------------------------------------------------- |
|
|
|
|
|
| `auth` | login, status, logout, list, switch, token, refresh, setup-git |
|
2026-05-13 21:57:07 +00:00
|
|
|
| `repo` | list, view, clone, create, fork, sync, edit, rename, archive, unarchive, delete, branches, topics, mirror, mirror-sync, watch, unwatch, star, unstar, starred |
|
|
|
|
|
| `issue` | list, view, create, edit, close, reopen, comment, edit-comment, delete-comment, develop |
|
|
|
|
|
| `pr` | list, view, create, edit, diff, commits, files, checks, ready, review, request-review, unrequest-review, status, checkout, merge, close, reopen |
|
2026-05-13 15:42:34 +00:00
|
|
|
| `release` | list, view, create, edit, delete, upload, download |
|
|
|
|
|
| `label` | list, create, edit, delete |
|
2026-05-13 21:57:07 +00:00
|
|
|
| `milestone`| list, view, create, edit, close, reopen, delete, assign |
|
2026-05-13 15:42:34 +00:00
|
|
|
| `run` | list, view, rerun, cancel (Forgejo Actions workflow runs) |
|
|
|
|
|
| `secret` | list, set, delete (Actions secrets) |
|
|
|
|
|
| `variable` | list, set, delete (Actions variables) |
|
2026-05-13 21:57:07 +00:00
|
|
|
| `search` | repos, issues, prs, users, code |
|
2026-05-13 15:42:34 +00:00
|
|
|
| `browse` | open the current repo (or a path within it) in your browser |
|
|
|
|
|
| `status` | notifications inbox + `--mark-read` |
|
|
|
|
|
| `org` | list, view, teams |
|
|
|
|
|
| `ssh-key` | list, add, delete |
|
|
|
|
|
| `gpg-key` | list, add, delete |
|
|
|
|
|
| `alias` | list, set, delete |
|
|
|
|
|
| `config` | get, set, list, path |
|
|
|
|
|
| `protect` | list, view, set, delete branch protection rules |
|
|
|
|
|
| `hook` | list, create, delete, test webhooks |
|
|
|
|
|
| `gist` | list, create (thin wrapper over `gist-*` repos) |
|
|
|
|
|
| `extension`| list, run discovered `fj-<name>` plugins on PATH |
|
|
|
|
|
| `api` | raw HTTP with `-X`, `-f`, `-F`, `-H`, `-q` (jq-ish), `--paginate`, `--include` |
|
|
|
|
|
| `completion`| Print shell completions (bash, zsh, fish, powershell, elvish) |
|
|
|
|
|
| `man` | Generate man pages into a directory |
|
|
|
|
|
|
|
|
|
|
## Global flags
|
|
|
|
|
|
|
|
|
|
- `--host <hostname>` (or `FJ_HOST`): pick the host explicitly.
|
|
|
|
|
- `--debug` (or `FJ_DEBUG=1`): log every HTTP request to stderr.
|
2026-05-13 21:57:07 +00:00
|
|
|
- `--no-pager` (or `FJ_NO_PAGER=1`): skip the pager.
|
|
|
|
|
- `--json-fields foo,bar`: gh-style projection on top of any `--json`
|
|
|
|
|
output. Dotted paths supported (`--json-fields owner.login,id`).
|
|
|
|
|
- `--web` on most list/view subcommands: open the relevant page in
|
|
|
|
|
your default browser.
|
2026-05-13 14:56:28 +00:00
|
|
|
|
|
|
|
|
## Config
|
|
|
|
|
|
2026-05-13 15:42:34 +00:00
|
|
|
- Hosts and the current host live in `$XDG_CONFIG_HOME/fj/hosts.toml`
|
|
|
|
|
(`~/Library/Application Support/fj/hosts.toml` on macOS).
|
|
|
|
|
- Aliases in `aliases.toml`. Preferences in `config.toml`.
|
|
|
|
|
- Tokens live in the OS keychain under service `fj`, keyed by hostname.
|
|
|
|
|
|
|
|
|
|
## Aliases
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
fj alias set co "pr checkout"
|
|
|
|
|
fj co 42 # equivalent to: fj pr checkout 42
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Extensions
|
|
|
|
|
|
|
|
|
|
Any executable on `$PATH` named `fj-<name>` is invokable as `fj <name> [args]`.
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
fj extension list # show discovered plugins
|
|
|
|
|
fj my-plugin some-arg # invokes `fj-my-plugin some-arg`
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Plugin-style usage of `fj api`
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# Auto-paginate a list endpoint into a single JSON array:
|
|
|
|
|
fj api /repos/search -f q=fj --paginate -q .
|
|
|
|
|
|
|
|
|
|
# Pass a custom request header:
|
|
|
|
|
fj api /user -H "X-Trace-Id: foo"
|
|
|
|
|
|
|
|
|
|
# Show response headers along with the body:
|
|
|
|
|
fj api /version --include
|
|
|
|
|
|
|
|
|
|
# Send a literal JSON body:
|
|
|
|
|
fj api /repos/migrate --input '{"clone_addr":"...","repo_name":"x","repo_owner":"y"}'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Hooks
|
|
|
|
|
|
|
|
|
|
- `hooks/pre-push` runs `cargo fmt --check`, `cargo clippy -D warnings`,
|
|
|
|
|
`cargo test`, and a release build before any push.
|
|
|
|
|
- With `FJ_E2E=1`, the hook also runs `scripts/e2e-smoke.sh` against the
|
|
|
|
|
configured host.
|
|
|
|
|
- Install via `./scripts/install-hooks.sh`.
|
|
|
|
|
|
|
|
|
|
## Building
|
|
|
|
|
|
|
|
|
|
```sh
|
docs: CLAUDE.md, CONTRIBUTING.md, CHANGELOG.md, docs/
* CLAUDE.md: project layout, key conventions, where to look first.
Captures the non-obvious things a future session needs.
* CONTRIBUTING.md: build/test workflow, how to add a subcommand
(concrete walkthrough), code style.
* CHANGELOG.md: history. 0.1.0 entry covers initial feature set;
Unreleased captures stability + optimization batch.
* docs/architecture.md: module graph, layering rules, the HTTP funnel,
pager + SIGINT, repo resolution, test strategy.
* docs/jq.md: --jq syntax cheatsheet (dot paths, brackets, negative
indices, pipes, what's not supported).
* docs/troubleshooting.md: keychain re-prompts, debug logging, pager
opt-out, alias precedence, hook bypass, common 401s.
* README.md: links into docs/ and updates binary size to 4 MB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 19:48:46 +00:00
|
|
|
cargo build --release # ~4 MB stripped binary at target/release/fj
|
2026-05-13 15:42:34 +00:00
|
|
|
./target/release/fj completion zsh > ~/.zfunc/_fj
|
|
|
|
|
./target/release/fj man -o ~/man/man1
|
|
|
|
|
```
|
2026-05-13 14:56:28 +00:00
|
|
|
|
docs: CLAUDE.md, CONTRIBUTING.md, CHANGELOG.md, docs/
* CLAUDE.md: project layout, key conventions, where to look first.
Captures the non-obvious things a future session needs.
* CONTRIBUTING.md: build/test workflow, how to add a subcommand
(concrete walkthrough), code style.
* CHANGELOG.md: history. 0.1.0 entry covers initial feature set;
Unreleased captures stability + optimization batch.
* docs/architecture.md: module graph, layering rules, the HTTP funnel,
pager + SIGINT, repo resolution, test strategy.
* docs/jq.md: --jq syntax cheatsheet (dot paths, brackets, negative
indices, pipes, what's not supported).
* docs/troubleshooting.md: keychain re-prompts, debug logging, pager
opt-out, alias precedence, hook bypass, common 401s.
* README.md: links into docs/ and updates binary size to 4 MB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 19:48:46 +00:00
|
|
|
## Documentation
|
|
|
|
|
|
|
|
|
|
- [`docs/architecture.md`](docs/architecture.md) — module graph, HTTP
|
|
|
|
|
funnel, pager + SIGINT, repo resolution
|
|
|
|
|
- [`docs/jq.md`](docs/jq.md) — `fj api --jq` projection syntax
|
|
|
|
|
- [`docs/troubleshooting.md`](docs/troubleshooting.md) — keychain
|
|
|
|
|
prompts, 401s, hook bypass, pager opt-out, alias precedence
|
|
|
|
|
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — build / test / release workflow
|
|
|
|
|
- [`CHANGELOG.md`](CHANGELOG.md) — release notes
|
|
|
|
|
|
2026-05-13 14:56:28 +00:00
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
MIT
|