A command line tool to connect forgejo instance.
Find a file
2026-06-21 12:46:41 +08:00
.agents/skills restructure: move fj skill to skills/fj-cli-guide, add agent symlink, drop AGENTS.md 2026-06-06 09:59:31 +08:00
skills/fj-cli-guide fix(review): list comments across pull request reviews 2026-06-21 12:33:02 +08:00
src fix(review): list comments across pull request reviews 2026-06-21 12:33:02 +08:00
tests fix(review): list comments across pull request reviews 2026-06-21 12:33:02 +08:00
.gitignore Phase 2: repo module (list, commits, create, fork, search) 2026-06-05 21:24:48 +08:00
Cargo.lock fix(review): list comments across pull request reviews 2026-06-21 12:33:02 +08:00
Cargo.toml build: switch to rustls, add prebuilt static binaries for 4 platforms 2026-06-09 19:45:18 +08:00
README.md Merge remote-tracking branch 'origin/master' 2026-06-21 12:46:41 +08:00
README_CN.md Merge remote-tracking branch 'origin/master' 2026-06-21 12:46:41 +08:00

fj — Forgejo CLI

fj is a command-line tool for Forgejo instances, analogous to gh for GitHub. Connect to any Forgejo instance (Codeberg, self-hosted) to manage repos, issues, PRs, branches, releases, and more.

Install

Prebuilt binaries

All static, drop into any Linux / Termux:

Platform Download
x86_64 (Linux) curl -L -o fj http://git.apas.com/attachments/57e3f6a1-6f16-4dc4-b925-e09616daf25f
aarch64 (Termux/RPi) curl -L -o fj http://git.apas.com/attachments/c8b7a584-f74e-44aa-800e-7dbad658c9e2
armv7 (RPi 32-bit) curl -L -o fj http://git.apas.com/attachments/d8e01084-05a1-4a49-88bd-7210b282766c
i686 (32-bit Linux) curl -L -o fj http://git.apas.com/attachments/119eda30-3de4-40e1-a182-45657bc583e8
chmod +x fj && mv fj $PREFIX/bin/   # Termux
# or
chmod +x fj && sudo mv fj /usr/local/bin/   # Linux

From crates.io

cargo install fj

Build from source

git clone https://github.com/your/fj.git
cd fj
cargo build --release

Configuration

fj connects to Forgejo via environment variables:

export FORGEJO_URL=https://codeberg.org
export FORGEJO_ACCESS_TOKEN=your_token_here

CLI flags also work (not recommended — exposed in shell history):

fj --forgejo-url https://codeberg.org --access-token your_token repo list

Create a token at Settings → Applications → Generate New Token in the Forgejo web UI.

Commands

Command Description
repo Repositories (list, commits, create, fork, search)
issue Issues (list, view, create, update, close, open, add-labels, remove-labels)
pr Pull Requests (list, view, create, update, merge, diff)
branch Branches (list, create, delete)
branch-protection Branch protection rules (list, view, create, edit, delete)
file Files (view, create, update, delete)
comment Comments (list, view, create, edit, delete)
review PR Reviews (list, view, create, list-comments)
release Releases (list, view, create, edit, delete)
workflow CI workflows (list, view, dispatch)
notification Notifications (list, view, mark-read, mark-all-read)
user Users (view, search)
milestone Milestones (list)
label Labels (list)
org Organizations (search-teams, list-labels)
time Time tracking (list, add, reset, delete, stopwatch)
issue-attach Issue attachments (list, view, download, create, edit, delete)
comment-attach Comment attachments (list, view, download, create, edit, delete)

Global Options

Option Description
--json JSON output (for scripting)
--help / -h Show help

Running fj without arguments prints the full help.


Detailed Usage

repo

# List your repos
fj repo list

# Search repos
fj repo search --query "rust" --language rust --limit 10

# Create a repo
fj repo create --name my-project --description "My new project" --private

# Create an org repo
fj repo create --name my-project --org my-org

# Fork a repo
fj repo fork --owner someone --repo their-project

# Fork into an org
fj repo fork --owner someone --repo their-project --org my-org

# View commit history
fj repo commits --owner someone --repo my-project --sha main --limit 20

issue

# List issues
fj issue list --owner someone --repo my-project --state open

# Filter by labels/milestone
fj issue list --owner someone --repo my-project --labels "bug,enhancement" --milestone "v1.0"

# View an issue
fj issue view --owner someone --repo my-project --index 42

# Create an issue
fj issue create --title "Bug: crash on startup" --body "Steps to reproduce..." --owner someone --repo my-project

# With labels and assignees
fj issue create --title "Feature request" --owner someone --repo my-project --labels "1,2" --assignees "alice,bob" --milestone 3

# Update an issue
fj issue update --owner someone --repo my-project --index 42 --title "Updated title" --state closed

# Close / re-open
fj issue close --owner someone --repo my-project --index 42
fj issue open --owner someone --repo my-project --index 42

# Manage labels
fj issue add-labels --owner someone --repo my-project --index 42 --labels "1,2,3"
fj issue remove-labels --owner someone --repo my-project --index 42 --labels "1"

pr

# List PRs
fj pr list --owner someone --repo my-project --state open

# View a PR
fj pr view --owner someone --repo my-project --index 10

# Create a PR
fj pr create --title "Add new feature" --head feature-branch --base main --owner someone --repo my-project

# With description and labels
fj pr create --title "Fix bug" --body "Fixes #42" --head fix/bug --base main --owner someone --repo my-project --labels "1" --assignees "alice"

# Update a PR
fj pr update --owner someone --repo my-project --index 10 --title "New title" --milestone 3

# Merge a PR
fj pr merge --owner someone --repo my-project --index 10

# Merge with a different strategy
fj pr merge --owner someone --repo my-project --index 10 --style squash --delete-branch

# View PR diff
fj pr diff --owner someone --repo my-project --index 10

# Diff a single file
fj pr diff --owner someone --repo my-project --index 10 --file src/main.rs

branch

# List branches
fj branch list --owner someone --repo my-project

# Create a branch
fj branch create --owner someone --repo my-project --name feature-x --ref main

# Delete a branch
fj branch delete --owner someone --repo my-project --name feature-x

branch-protection

# List protection rules
fj branch-protection list --owner someone --repo my-project

# View a rule
fj branch-protection view --owner someone --repo my-project --name main

# Create a rule
fj branch-protection create --owner someone --repo my-project --branch-name "main" --required-approvals 1 --enable-push

# Edit a rule
fj branch-protection edit --owner someone --repo my-project --name main --required-approvals 2

# Delete a rule
fj branch-protection delete --owner someone --repo my-project --name main

file

# View a file
fj file view --owner someone --repo my-project --path README.md

# From a specific branch
fj file view --owner someone --repo my-project --path src/main.rs --ref develop

# With line range
fj file view --owner someone --repo my-project --path Cargo.toml --start-line 1 --end-line 20

# Create a file
fj file create --owner someone --repo my-project --path docs/notes.md --content "# Notes" --message "Add notes"

# Create on a new branch
fj file create --owner someone --repo my-project --path new-feature.md --content "..." --branch main --new-branch feature/docs

# Update a file (needs current SHA)
fj file update --owner someone --repo my-project --path README.md --content "Updated" --sha abc1234

# Delete a file
fj file delete --owner someone --repo my-project --path old-file.txt --sha abc1234

comment

# List issue comments
fj comment list --owner someone --repo my-project --type issue --index 42

# List PR comments
fj comment list --owner someone --repo my-project --type pr --index 10

# View a comment
fj comment view --owner someone --repo my-project --comment-id 123

# Add a comment
fj comment create --owner someone --repo my-project --type issue --index 42 --body "Looks good!"

# Edit a comment
fj comment edit --owner someone --repo my-project --comment-id 123 --body "Updated comment"

# Delete a comment
fj comment delete --owner someone --repo my-project --comment-id 123

review

# List PR reviews
fj review list --owner someone --repo my-project --pr-index 10

# View a review
fj review view --owner someone --repo my-project --pr-index 10 --review-id 5

# Approve
fj review create --owner someone --repo my-project --pr-index 10 --state APPROVED --body "LGTM!"

# Request changes
fj review create --owner someone --repo my-project --pr-index 10 --state REQUEST_CHANGES --body "Please fix the null check"

# List inline review comments across all reviews on a PR
fj review list-comments --owner someone --repo my-project --pr-index 10

# List inline review comments for one review
fj review list-comments --owner someone --repo my-project --pr-index 10 --review-id 5

release

# List releases
fj release list --owner someone --repo my-project

# Filter by type
fj release list --owner someone --repo my-project --filter draft
fj release list --owner someone --repo my-project --filter prerelease

# View latest release
fj release view --owner someone --repo my-project --latest

# View by tag
fj release view --owner someone --repo my-project --tag v1.0.0

# Create a release
fj release create --owner someone --repo my-project --tag-name v1.0.0 --name "First Release"

# Create draft / pre-release
fj release create --owner someone --repo my-project --tag-name v2.0.0-beta --name "Beta" --prerelease --draft

# Edit a release
fj release edit --owner someone --repo my-project --id 1 --name "Updated Name" --draft false

# Delete a release
fj release delete --owner someone --repo my-project --id 1
fj release delete --owner someone --repo my-project --tag v1.0.0

# Release attachments
fj release attachment list --owner someone --repo my-project --release-id 1
fj release attachment download --owner someone --repo my-project --release-id 1 --attachment-id 5
fj release attachment create --owner someone --repo my-project --release-id 1 --file ./build/output.tar.gz

workflow

# List workflow runs
fj workflow list --owner someone --repo my-project

# View a run
fj workflow view --owner someone --repo my-project --run-id 123

# Dispatch a workflow
fj workflow dispatch --owner someone --repo my-project --workflow ci.yml --ref main

# Dispatch with inputs
fj workflow dispatch --owner someone --repo my-project --workflow release.yml --ref main --inputs "version=1.0.0,dry_run=false"

notification

# List unread notifications
fj notification list

# Include read
fj notification list --all

# Filter by repo
fj notification list --repo someone/my-project

# View a notification
fj notification view --id 123

# Mark read
fj notification mark-read --id 123
fj notification mark-all-read

# Mark all read for a repo
fj notification mark-all-read --repo someone/my-project

user

# View current user
fj user view

# View a specific user
fj user view --username alice

# Search users
fj user search --query "john"

time

# List time records for an issue
fj time list --type issue --owner someone --repo my-project --index 42

# List time for a repo
fj time list --type repo --owner someone --repo my-project

# Add time (seconds)
fj time add --owner someone --repo my-project --index 42 --time 3600

# Reset all time on an issue
fj time reset --owner someone --repo my-project --index 42

# Delete an entry
fj time delete --owner someone --repo my-project --index 42 --id 5

# Stopwatch
fj time stopwatch start --owner someone --repo my-project --index 42
fj time stopwatch stop --owner someone --repo my-project --index 42
fj time stopwatch cancel --owner someone --repo my-project --index 42
fj time stopwatch list

Attachments

# Issue attachments
fj issue-attach list --owner someone --repo my-project --index 42
fj issue-attach download --owner someone --repo my-project --index 42 --attachment-id 5
fj issue-attach create --owner someone --repo my-project --index 42 --file ./screenshot.png

# Comment attachments
fj comment-attach list --owner someone --repo my-project --comment-id 123
fj comment-attach download --owner someone --repo my-project --comment-id 123 --attachment-id 5

JSON Output

All commands support --json for structured output:

fj --json issue list --owner someone --repo my-project | jq '.[] | {number, title}'

License

Apache-2.0 OR MIT