feat: v0.3.0a — add api command, pr diff/comment/review, structured errors

New commands:
- fgj api: raw REST API passthrough with field inference and path interpolation
- fgj pr diff: view PR diffs with color, --name-only, --stat
- fgj pr comment: add comments to pull requests
- fgj pr review: approve, request changes, or comment on PRs

Agentic enhancements:
- --json-errors flag for structured JSON error output on stderr
- APIError type wrapping HTTP status codes for machine consumption
- Error codes: auth_required, not_found, api_error, invalid_input, etc.

Docs updated for forgejo.zerova.net/sid/fgj-sid fork.
This commit is contained in:
sid 2026-03-21 21:50:24 -06:00
parent 50191cc542
commit 43e43e7024
17 changed files with 64 additions and 64 deletions

View file

@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [0.3.0a] - 2026-03-21
### Added ### Added
@ -165,6 +165,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Cobra framework for CLI structure - Cobra framework for CLI structure
- Viper for configuration management - Viper for configuration management
[0.3.0a]: https://forgejo.zerova.net/sid/fgj-sid/releases/tag/v0.3.0a
[0.3.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.3.0 [0.3.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.3.0
[0.2.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.2.0 [0.2.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.2.0
[0.1.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.1.0 [0.1.0]: https://codeberg.org/romaintb/fgj/releases/tag/v0.1.0

View file

@ -1,14 +1,15 @@
# fgj - Forgejo CLI Tool # fgj - Forgejo/Gitea CLI Tool
[![Go Version](https://img.shields.io/badge/Go-1.23+-00ADD8?style=flat-square&logo=go)](https://golang.org) [![Go Version](https://img.shields.io/badge/Go-1.23+-00ADD8?style=flat-square&logo=go)](https://golang.org)
[![CI Status](https://codeberg.org/romaintb/fgj/actions/workflows/ci.yml/badge.svg)](https://codeberg.org/romaintb/fgj/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE)
`fgj` is a command-line tool for working with Forgejo instances (including Codeberg.org). It brings pull requests, issues, and other Forgejo concepts to the terminal, similar to what `gh` does for GitHub. `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 ## Features
- Multi-instance support (works with any Forgejo instance) - Multi-instance support (works with any Forgejo or Gitea instance)
- Pull request management (create, list, view, merge, diff, comment, review) - Pull request management (create, list, view, merge, diff, comment, review)
- Issue tracking (create, list, view, comment, close, labels) - Issue tracking (create, list, view, comment, close, labels)
- Repository operations (view, list, create, clone, fork) - Repository operations (view, list, create, clone, fork)
@ -25,49 +26,43 @@
## Installation ## Installation
[![Packaging status](https://repology.org/badge/vertical-allrepos/fgj.svg)](https://repology.org/project/fgj/versions)
### Arch Linux (AUR)
`fgj` is available in the Arch User Repository:
```bash
yay -S fgj
```
### macOS (Homebrew) ### macOS (Homebrew)
```bash ```bash
brew tap romaintb/fgj https://codeberg.org/romaintb/homebrew-fgj.git brew tap sid/fgj-sid https://forgejo.zerova.net/sid/homebrew-fgj-sid.git
brew install fgj brew install fgj
``` ```
### Using Go Install ### Using Go Install
```bash ```bash
go install codeberg.org/romaintb/fgj@latest go install forgejo.zerova.net/sid/fgj-sid@latest
``` ```
### Other Distributions ### From Source
We'd love your help packaging `fgj` for other distributions! If you're interested in creating packages for Debian, Ubuntu, Fedora, or any packaging systems, please open an issue or reach out. ```bash
git clone https://forgejo.zerova.net/sid/fgj-sid.git
cd fgj-sid
go build -o fgj .
```
## Quick Start ## Quick Start
### 1. Authenticate ### 1. Authenticate
First, authenticate with your Forgejo instance: First, authenticate with your Forgejo or Gitea instance:
```bash ```bash
fgj auth login fgj auth login
``` ```
You'll be prompted for: You'll be prompted for:
- Forgejo instance hostname (default: codeberg.org) - Instance hostname (default: codeberg.org)
- Personal access token - Personal access token
To create a personal access token: To create a personal access token:
1. Go to your Forgejo instance (e.g., https://codeberg.org) 1. Go to your instance (e.g., https://forgejo.zerova.net)
2. Navigate to Settings > Applications > Generate New Token 2. Navigate to Settings > Applications > Generate New Token
3. Give it appropriate permissions (repo, issue, etc.) 3. Give it appropriate permissions (repo, issue, etc.)
4. Copy the token and paste it when prompted 4. Copy the token and paste it when prompted
@ -105,7 +100,7 @@ fgj pr view 123 # Automatically uses current repo
fgj pr list -R owner/repo 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 Forgejo instance hostname. If you're not in a git repository, you'll need to use the `-R` flag. 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 ### Pull Requests
@ -376,21 +371,21 @@ Configuration is stored in `~/.config/fgj/config.yaml`:
```yaml ```yaml
hosts: hosts:
codeberg.org: forgejo.zerova.net:
hostname: codeberg.org hostname: forgejo.zerova.net
token: your_token_here token: your_token_here
user: your_username user: your_username
git_protocol: https git_protocol: ssh
my-forgejo.com: codeberg.org:
hostname: my-forgejo.com hostname: codeberg.org
token: another_token token: another_token
user: another_username user: another_username
git_protocol: ssh git_protocol: https
``` ```
### Environment Variables ### Environment Variables
- `FGJ_HOST`: Override the default Forgejo instance (auto-detected from git remote if not set) - `FGJ_HOST`: Override the default instance (auto-detected from git remote if not set)
- `FGJ_TOKEN`: Provide authentication token - `FGJ_TOKEN`: Provide authentication token
Hostname is resolved in this priority order: Hostname is resolved in this priority order:
@ -401,10 +396,10 @@ Hostname is resolved in this priority order:
### Command-line Flags ### Command-line Flags
- `--hostname`: Specify Forgejo instance for a command (overrides auto-detection and environment variables) - `--hostname`: Specify instance for a command (overrides auto-detection and environment variables)
- `--config`: Use a custom config file - `--config`: Use a custom config file
When working in a git repository, `fgj` automatically detects the Forgejo instance from your origin remote URL, so you typically don't need to specify `--hostname` unless working with multiple instances. 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 ## Use with AI Coding Agents
@ -442,21 +437,21 @@ fgj api /repos/{owner}/{repo}/labels -X POST -f name=agent-reviewed -f color="#0
fgj pr view 9999 --json --json-errors 2>errors.json fgj pr view 9999 --json --json-errors 2>errors.json
``` ```
## Supported Forgejo Instances ## Supported Instances
`fgj` works with any Forgejo instance, including: `fgj` works with any Forgejo or Gitea instance, including:
- [Codeberg.org](https://codeberg.org) (default)
- Self-hosted Forgejo instances - Self-hosted Forgejo instances
- Gitea instances (compatible API) - Self-hosted Gitea instances
- [Codeberg.org](https://codeberg.org)
## Contributing ## Contributing
Contributions are welcome! Please feel free to submit a Pull Request. 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 ## Missing Features / Roadmap
`fgj` aims to be a drop-in replacement for `gh` when working with Forgejo instances. While we've implemented the core features, some `gh` commands are not yet available: `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:** **Not Yet Implemented:**
- `run delete` - Delete a workflow run - `run delete` - Delete a workflow run
@ -467,7 +462,11 @@ Contributions are welcome! Please feel free to submit a Pull Request.
- `release edit`, `release download`, `release generate-notes` - `release edit`, `release download`, `release generate-notes`
- `repo delete`, `repo rename`, `repo visibility` - `repo delete`, `repo rename`, `repo visibility`
We welcome contributions to implement any of these features! Please check the issues or create a new one to discuss implementation before starting work. 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 ## License

View file

@ -12,8 +12,8 @@ import (
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
) )
// ActionRun represents a workflow run // ActionRun represents a workflow run

View file

@ -10,8 +10,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"codeberg.org/romaintb/fgj/internal/git" "forgejo.zerova.net/sid/fgj-sid/internal/git"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -7,8 +7,8 @@ import (
"strings" "strings"
"syscall" "syscall"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"golang.org/x/term" "golang.org/x/term"

View file

@ -5,7 +5,7 @@ import (
"errors" "errors"
"os" "os"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
) )
// Error codes for structured error output. // Error codes for structured error output.

View file

@ -8,8 +8,8 @@ import (
"text/tabwriter" "text/tabwriter"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -8,8 +8,8 @@ import (
"text/tabwriter" "text/tabwriter"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -6,8 +6,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/term" "golang.org/x/term"
) )

View file

@ -7,8 +7,8 @@ import (
"strconv" "strconv"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -9,8 +9,8 @@ import (
"time" "time"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -9,8 +9,8 @@ import (
"text/tabwriter" "text/tabwriter"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/api" "forgejo.zerova.net/sid/fgj-sid/internal/api"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

View file

@ -5,7 +5,7 @@ import (
"os" "os"
"strings" "strings"
"codeberg.org/romaintb/fgj/internal/git" "forgejo.zerova.net/sid/fgj-sid/internal/git"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -18,7 +18,7 @@ var rootCmd = &cobra.Command{
Short: "Forgejo CLI tool - work seamlessly with Forgejo from the command line", Short: "Forgejo CLI tool - work seamlessly with Forgejo from the command line",
Long: `fgj is a command line tool for Forgejo instances (including Codeberg). Long: `fgj is a command line tool for Forgejo instances (including Codeberg).
It brings pull requests, issues, and other Forgejo concepts to the terminal.`, It brings pull requests, issues, and other Forgejo concepts to the terminal.`,
Version: "0.2.0", Version: "0.3.0a",
SilenceErrors: true, SilenceErrors: true,
} }

2
go.mod
View file

@ -1,4 +1,4 @@
module codeberg.org/romaintb/fgj module forgejo.zerova.net/sid/fgj-sid
go 1.23.0 go 1.23.0

View file

@ -8,7 +8,7 @@ import (
"net/http" "net/http"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
) )
type Client struct { type Client struct {

View file

@ -3,7 +3,7 @@ package api
import ( import (
"testing" "testing"
"codeberg.org/romaintb/fgj/internal/config" "forgejo.zerova.net/sid/fgj-sid/internal/config"
) )
func TestClient_Hostname(t *testing.T) { func TestClient_Hostname(t *testing.T) {

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"codeberg.org/romaintb/fgj/cmd" "forgejo.zerova.net/sid/fgj-sid/cmd"
) )
func main() { func main() {