Add PR checks command, iostreams/text packages for colored table output, top-level run/workflow aliases matching gh CLI structure. Enhance actions, issues, PRs, releases, repos, labels, milestones, and wiki commands with improved flags, JSON output, and error handling.
550 lines
14 KiB
Markdown
550 lines
14 KiB
Markdown
# fgj - Forgejo/Gitea CLI Tool
|
|
|
|
[](https://golang.org)
|
|
[](LICENSE)
|
|
|
|
`fgj` is a command-line tool for working with Forgejo and Gitea instances. It brings pull requests, issues, and other forge concepts to the terminal, similar to what `gh` does for GitHub. This fork adds agentic dev features — raw API access, PR review workflows, structured error output, and machine-readable I/O for AI coding agents.
|
|
|
|
> Forked from [codeberg.org/romaintb/fgj](https://codeberg.org/romaintb/fgj) and hosted at [forgejo.zerova.net/sid/fgj-sid](https://forgejo.zerova.net/sid/fgj-sid).
|
|
|
|
## Features
|
|
|
|
- Multi-instance support (works with any Forgejo or Gitea instance)
|
|
- Pull request management (create, list, view, merge, diff, comment, review)
|
|
- Issue tracking (create, list, view, comment, close, labels)
|
|
- Repository operations (view, list, create, edit, clone, fork)
|
|
- Label management (list, create, edit, delete)
|
|
- Milestone management (list, view, create, edit, delete)
|
|
- Wiki page management (list, view, create, edit, delete)
|
|
- Issue dependencies (`--add-dependency`, `--remove-dependency`)
|
|
- Forgejo Actions (workflow runs, watch/rerun/cancel, enable/disable, secrets, variables)
|
|
- Releases (create, upload, delete)
|
|
- Raw API access (`fgj api`) for arbitrary REST calls
|
|
- Shell completions (bash, zsh, fish, PowerShell) and man pages
|
|
- JSON output (`--json`) for all list/view commands
|
|
- Structured JSON error output (`--json-errors`) for machine consumption
|
|
- Automatic repository and hostname detection from git context
|
|
- Secure authentication with personal access tokens
|
|
- XDG Base Directory compliant config location
|
|
- AI coding agent friendly
|
|
|
|
## Installation
|
|
|
|
### macOS (Homebrew)
|
|
|
|
```bash
|
|
brew tap sid/fgj-sid https://forgejo.zerova.net/sid/homebrew-fgj-sid.git
|
|
brew install fgj
|
|
```
|
|
|
|
### Using Go Install
|
|
|
|
```bash
|
|
go install forgejo.zerova.net/sid/fgj-sid@latest
|
|
```
|
|
|
|
### From Source
|
|
|
|
```bash
|
|
git clone https://forgejo.zerova.net/sid/fgj-sid.git
|
|
cd fgj-sid
|
|
go build -o fgj .
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### 1. Authenticate
|
|
|
|
First, authenticate with your Forgejo or Gitea instance:
|
|
|
|
```bash
|
|
fgj auth login
|
|
```
|
|
|
|
You'll be prompted for:
|
|
- Instance hostname (default: codeberg.org)
|
|
- Personal access token
|
|
|
|
To create a personal access token:
|
|
1. Go to your instance (e.g., https://forgejo.zerova.net)
|
|
2. Navigate to Settings > Applications > Generate New Token
|
|
3. Give it appropriate permissions (repo, issue, etc.)
|
|
4. Copy the token and paste it when prompted
|
|
|
|
### 2. Check Authentication Status
|
|
|
|
```bash
|
|
fgj auth status
|
|
```
|
|
|
|
### Auth Helpers
|
|
|
|
```bash
|
|
# Print the stored token for the current host
|
|
fgj auth token
|
|
|
|
# Remove authentication for a host
|
|
fgj auth logout
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Repository Detection
|
|
|
|
`fgj` automatically detects the repository from your git context, similar to `gh`:
|
|
|
|
```bash
|
|
# When inside a git repository, no -R flag needed!
|
|
cd /path/to/your/repo
|
|
fgj pr list # Automatically uses current repo
|
|
fgj issue list # Automatically uses current repo
|
|
fgj pr view 123 # Automatically uses current repo
|
|
|
|
# Or explicitly specify a repository with -R
|
|
fgj pr list -R owner/repo
|
|
```
|
|
|
|
The tool reads `.git/config` to find the origin remote and extract both the owner/repo information and the instance hostname. If you're not in a git repository, you'll need to use the `-R` flag.
|
|
|
|
### Pull Requests
|
|
|
|
```bash
|
|
# List pull requests (auto-detects repo and hostname from git)
|
|
fgj pr list
|
|
|
|
# Or specify explicitly
|
|
fgj pr list -R owner/repo
|
|
|
|
# Filter by state
|
|
fgj pr list --state closed
|
|
|
|
# View a specific pull request
|
|
fgj pr view 123
|
|
|
|
# Create a pull request
|
|
fgj pr create -t "PR Title" -b "PR Description" -H feature-branch -B main
|
|
|
|
# Merge a pull request
|
|
fgj pr merge 123 --merge-method squash
|
|
|
|
# View PR diff
|
|
fgj pr diff 123
|
|
|
|
# View diff with color
|
|
fgj pr diff 123 --color always
|
|
|
|
# Show only changed file names
|
|
fgj pr diff 123 --name-only
|
|
|
|
# Show diffstat summary
|
|
fgj pr diff 123 --stat
|
|
|
|
# Comment on a pull request
|
|
fgj pr comment 123 -b "Looks good, minor nit on line 42"
|
|
|
|
# Comment from a file
|
|
fgj pr comment 123 --body-file review-notes.md
|
|
|
|
# Approve a pull request
|
|
fgj pr review 123 --approve -b "LGTM"
|
|
|
|
# Request changes
|
|
fgj pr review 123 --request-changes -b "Please fix the error handling"
|
|
|
|
# Submit a review comment (neither approve nor request changes)
|
|
fgj pr review 123 --comment -b "Some observations"
|
|
```
|
|
|
|
### Issues
|
|
|
|
```bash
|
|
# List issues (auto-detects repo and hostname from git)
|
|
fgj issue list
|
|
|
|
# Or specify explicitly
|
|
fgj issue list -R owner/repo
|
|
|
|
# Filter by state
|
|
fgj issue list --state all
|
|
|
|
# View an issue
|
|
fgj issue view 456
|
|
|
|
# Create an issue
|
|
fgj issue create -t "Issue Title" -b "Issue Description"
|
|
|
|
# Create an issue with labels
|
|
fgj issue create -t "Issue Title" -b "Issue Description" -l bug -l enhancement
|
|
|
|
# Comment on an issue
|
|
fgj issue comment 456 -b "My comment"
|
|
|
|
# Close an issue
|
|
fgj issue close 456
|
|
|
|
# Close an issue with a comment
|
|
fgj issue close 456 -c "Fixed in v2.0"
|
|
|
|
# Edit an issue (title, body, state, labels)
|
|
fgj issue edit 456 -t "New Title"
|
|
fgj issue edit 456 --add-label priority --remove-label bug
|
|
|
|
# Manage issue dependencies
|
|
fgj issue edit 456 --add-dependency 123
|
|
fgj issue edit 456 --remove-dependency 123
|
|
```
|
|
|
|
### Labels
|
|
|
|
```bash
|
|
# List labels
|
|
fgj label list
|
|
|
|
# Create a label
|
|
fgj label create bug --color ff0000 -d "Something isn't working"
|
|
|
|
# Edit a label
|
|
fgj label edit bug --name bugfix --color ee0000
|
|
|
|
# Delete a label
|
|
fgj label delete bug
|
|
```
|
|
|
|
### Milestones
|
|
|
|
```bash
|
|
# List milestones
|
|
fgj milestone list
|
|
fgj milestone list --state all
|
|
|
|
# View a milestone
|
|
fgj milestone view "v1.0"
|
|
|
|
# Create a milestone with due date
|
|
fgj milestone create "v2.0" -d "Next major release" --due 2026-06-01
|
|
|
|
# Edit a milestone
|
|
fgj milestone edit "v2.0" --title "v2.0-rc1" --state closed
|
|
|
|
# Delete a milestone
|
|
fgj milestone delete "v2.0"
|
|
```
|
|
|
|
### Wiki
|
|
|
|
```bash
|
|
# List wiki pages
|
|
fgj wiki list
|
|
|
|
# View a wiki page
|
|
fgj wiki view "Home"
|
|
|
|
# Create a wiki page
|
|
fgj wiki create "Setup Guide" -b "# Setup\n\nFollow these steps..."
|
|
|
|
# Create from file
|
|
fgj wiki create "API Docs" --body-file docs/api.md
|
|
|
|
# Edit a wiki page
|
|
fgj wiki edit "Home" -b "Updated content"
|
|
|
|
# Delete a wiki page
|
|
fgj wiki delete "Old Page"
|
|
```
|
|
|
|
### Repositories
|
|
|
|
```bash
|
|
# View repository details
|
|
fgj repo view owner/repo
|
|
|
|
# List your repositories
|
|
fgj repo list
|
|
|
|
# Create a repository
|
|
fgj repo create my-repo
|
|
fgj repo create my-repo -d "My project" --private --add-readme -g Go -l MIT
|
|
|
|
# Clone a repository
|
|
fgj repo clone owner/repo
|
|
|
|
# Clone via SSH
|
|
fgj repo clone owner/repo -p ssh
|
|
|
|
# Fork a repository
|
|
fgj repo fork owner/repo
|
|
|
|
# Edit repository settings
|
|
fgj repo edit owner/repo --public
|
|
fgj repo edit owner/repo --private
|
|
fgj repo edit owner/repo -d "New description" --homepage https://example.com
|
|
fgj repo edit --default-branch develop
|
|
fgj repo edit owner/repo --name new-name
|
|
|
|
# Rename a repository (shorthand)
|
|
fgj repo rename new-name
|
|
fgj repo rename new-name -R owner/old-name
|
|
```
|
|
|
|
### Releases
|
|
|
|
```bash
|
|
# List releases
|
|
fgj release list
|
|
|
|
# View a release (or use "latest")
|
|
fgj release view v1.2.3
|
|
|
|
# Create a release with notes and optional assets
|
|
fgj release create v1.2.3 -t "v1.2.3" -n "Release notes" ./dist/app.tar.gz
|
|
|
|
# Upload assets to an existing release
|
|
fgj release upload v1.2.3 ./dist/app.tar.gz --clobber
|
|
|
|
# Delete a release (keeps the Git tag)
|
|
fgj release delete v1.2.3
|
|
```
|
|
|
|
### Forgejo Actions
|
|
|
|
```bash
|
|
# List workflows
|
|
fgj actions workflow list
|
|
|
|
# View a workflow
|
|
fgj actions workflow view ci.yml
|
|
|
|
# Run a workflow (trigger workflow_dispatch)
|
|
fgj actions workflow run deploy.yml
|
|
|
|
# Run a workflow with inputs
|
|
fgj actions workflow run deploy.yml -f environment=production -f version=1.2.3
|
|
|
|
# Run a workflow on a specific branch
|
|
fgj actions workflow run deploy.yml -r feature-branch
|
|
|
|
# Enable or disable a workflow
|
|
fgj actions workflow enable ci.yml
|
|
fgj actions workflow disable ci.yml
|
|
|
|
# List workflow runs
|
|
fgj actions run list
|
|
|
|
# View a specific run
|
|
fgj actions run view 123
|
|
|
|
# View run with job details
|
|
fgj actions run view 123 --verbose
|
|
|
|
# View run logs
|
|
fgj actions run view 123 --log
|
|
|
|
# View specific job logs
|
|
fgj actions run view 123 --job 456 --log
|
|
|
|
# Watch a run until completion
|
|
fgj actions run watch 123
|
|
|
|
# Rerun a workflow run
|
|
fgj actions run rerun 123
|
|
|
|
# Cancel a running workflow
|
|
fgj actions run cancel 123
|
|
|
|
# List secrets
|
|
fgj actions secret list
|
|
|
|
# Create a secret
|
|
fgj actions secret create MY_SECRET
|
|
|
|
# Delete a secret
|
|
fgj actions secret delete MY_SECRET
|
|
|
|
# List variables
|
|
fgj actions variable list
|
|
|
|
# Get a variable
|
|
fgj actions variable get MY_VAR
|
|
|
|
# Create a variable
|
|
fgj actions variable create MY_VAR "value"
|
|
|
|
# Update a variable
|
|
fgj actions variable update MY_VAR "new value"
|
|
|
|
# Delete a variable
|
|
fgj actions variable delete MY_VAR
|
|
```
|
|
|
|
### Raw API Access
|
|
|
|
```bash
|
|
# GET request (auto-detects owner/repo from git context)
|
|
fgj api /repos/{owner}/{repo}/pulls
|
|
|
|
# POST with fields
|
|
fgj api /repos/{owner}/{repo}/issues -X POST -f title="Bug report" -f body="Description"
|
|
|
|
# Explicit method and hostname
|
|
fgj api /repos/myorg/myrepo/labels --hostname my-forgejo.example.com
|
|
|
|
# Read request body from file
|
|
fgj api /repos/{owner}/{repo}/issues -X POST --input issue.json
|
|
|
|
# Read from stdin
|
|
echo '{"title":"test"}' | fgj api /repos/{owner}/{repo}/issues -X POST --input -
|
|
|
|
# Include response headers
|
|
fgj api /repos/{owner}/{repo} -i
|
|
|
|
# Suppress output (useful for DELETE)
|
|
fgj api /repos/{owner}/{repo}/issues/123 -X DELETE --silent
|
|
```
|
|
|
|
## Shell Completions and Man Pages
|
|
|
|
```bash
|
|
# Generate shell completion scripts
|
|
fgj completion bash > /etc/bash_completion.d/fgj
|
|
fgj completion zsh > "${fpath[1]}/_fgj"
|
|
fgj completion fish > ~/.config/fish/completions/fgj.fish
|
|
|
|
# Generate man pages to a directory
|
|
fgj manpages --dir ~/.local/share/man/man1
|
|
```
|
|
|
|
## JSON Output
|
|
|
|
Most list and view commands support `--json` for machine-readable output:
|
|
|
|
```bash
|
|
fgj pr list --json
|
|
fgj issue view 456 --json
|
|
fgj release list --json
|
|
fgj actions run list --json
|
|
fgj actions workflow view ci.yml --json
|
|
|
|
# Get JSON output from PR comment/review
|
|
fgj pr comment 123 -b "LGTM" --json
|
|
fgj pr review 123 --approve -b "Ship it" --json
|
|
```
|
|
|
|
### Structured Error Output
|
|
|
|
For machine consumption (ideal for AI agents and scripts), use `--json-errors` to get structured JSON errors on stderr:
|
|
|
|
```bash
|
|
# Errors are written to stderr as JSON
|
|
fgj pr view 9999 --json-errors
|
|
# stderr: {"error":{"code":"not_found","message":"...","status":404}}
|
|
|
|
# Combine with --json for fully machine-readable I/O
|
|
fgj pr list --json --json-errors
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Configuration is stored in `~/.config/fgj/config.yaml`:
|
|
|
|
```yaml
|
|
hosts:
|
|
forgejo.zerova.net:
|
|
hostname: forgejo.zerova.net
|
|
token: your_token_here
|
|
user: your_username
|
|
git_protocol: ssh
|
|
codeberg.org:
|
|
hostname: codeberg.org
|
|
token: another_token
|
|
user: another_username
|
|
git_protocol: https
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
- `FGJ_HOST`: Override the default instance (auto-detected from git remote if not set)
|
|
- `FGJ_TOKEN`: Provide authentication token
|
|
|
|
Hostname is resolved in this priority order:
|
|
1. Command-specific flags (e.g., `--hostname`)
|
|
2. `FGJ_HOST` environment variable
|
|
3. Auto-detected from git remote URL
|
|
4. Default to `codeberg.org`
|
|
|
|
### Command-line Flags
|
|
|
|
- `--hostname`: Specify instance for a command (overrides auto-detection and environment variables)
|
|
- `--config`: Use a custom config file
|
|
|
|
When working in a git repository, `fgj` automatically detects the instance from your origin remote URL, so you typically don't need to specify `--hostname` unless working with multiple instances.
|
|
|
|
## Use with AI Coding Agents
|
|
|
|
`fgj` is designed to work seamlessly with AI coding agents like Claude Code. Use `--json` and `--json-errors` for fully machine-readable I/O:
|
|
|
|
```bash
|
|
# Create PR from agent's changes
|
|
fgj pr create -R owner/repo -t "feat: add new feature" -b "$(cat <<EOF
|
|
## Summary
|
|
- Added new feature X
|
|
- Fixed bug Y
|
|
|
|
Generated with AI assistance
|
|
EOF
|
|
)" --json
|
|
|
|
# Check PR status during development
|
|
fgj pr list -R owner/repo --state open --json
|
|
|
|
# Review a PR diff, then approve
|
|
fgj pr diff 123
|
|
fgj pr review 123 --approve -b "LGTM" --json
|
|
|
|
# Post review feedback
|
|
fgj pr comment 123 -b "Consider using a map here for O(1) lookup" --json
|
|
|
|
# Request changes with detailed feedback
|
|
fgj pr review 123 --request-changes --body-file feedback.md --json
|
|
|
|
# Use raw API for anything not covered by commands
|
|
fgj api /repos/{owner}/{repo}/topics --json-errors
|
|
fgj api /repos/{owner}/{repo}/labels -X POST -f name=agent-reviewed -f color="#00ff00"
|
|
|
|
# Fully machine-readable error handling
|
|
fgj pr view 9999 --json --json-errors 2>errors.json
|
|
```
|
|
|
|
## Supported Instances
|
|
|
|
`fgj` works with any Forgejo or Gitea instance, including:
|
|
|
|
- Self-hosted Forgejo instances
|
|
- Self-hosted Gitea instances
|
|
- [Codeberg.org](https://codeberg.org)
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please feel free to submit a Pull Request at [forgejo.zerova.net/sid/fgj-sid](https://forgejo.zerova.net/sid/fgj-sid).
|
|
|
|
## Missing Features / Roadmap
|
|
|
|
`fgj` aims to be a drop-in replacement for `gh` when working with Forgejo and Gitea instances. While we've implemented the core features, some `gh` commands are not yet available:
|
|
|
|
**Not Yet Implemented:**
|
|
- `run delete` - Delete a workflow run
|
|
- `run download` - Download workflow run artifacts
|
|
- `pr checkout`, `pr close/reopen`
|
|
- `pr checks`, `pr ready/draft`
|
|
- `issue reopen`, `issue assign`
|
|
- `release edit`, `release download`, `release generate-notes`
|
|
- `repo delete`
|
|
|
|
We welcome contributions to implement any of these features!
|
|
|
|
## Acknowledgments
|
|
|
|
Based on [fgj by romaintb](https://codeberg.org/romaintb/fgj). Enhanced with agentic dev features for AI-assisted workflows.
|
|
|
|
## License
|
|
|
|
MIT License
|