CHANGELOG.md updated with the audit-driven hardening pass spanning 13 findings across cmd/ and internal/. Adds CLAUDE.md documenting dev workflow, codex review pattern, release process, and homebrew tap update steps.
13 KiB
13 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.4.0] - 2026-05-02
Audit-driven hardening pass. Three reviewers (Codex + two Claude agents with non-overlapping focuses) found 13 issues across cmd/ and internal/; this release ships fixes for all 13.
BREAKING
--json=fieldssyntax removed. The flag was a string withNoOptDefVal=" "sentinel —--jsonalone meant "everything",--json=fieldsprojected. That produced--json string[=" "]in--helpand required a literal=because--json fieldswas parsed as the bare flag plus a positional. Migration:--json=fields→--json-fields fields. Bare--jsonstill means "all fields as JSON".--jsonand--json-fieldsare mutually exclusive;--jqcomposes with either.
Added
fj api --json/--json-fields/--jq— projection and jq filtering for raw API responses. Routes through the sameaddJSONFlagshelpers as the other list commands. Closes the inconsistency wherefj apiwas the only command returning raw JSON without these knobs.fj api --paginate— follows RFC 5988Link: rel="next"headers and concatenates JSON array pages, gh-compatible. Validates same-origin before forwarding the bearer token to the next URL.cmd/paginate.go— genericpaginateGitea[T any]helper. Applied torepo list,pr list,issue list. Previously onlyrelease listwalked pages; the others passedPageSize: limitdirectly to the gitea SDK, which silently caps PageSize at 50, so--limit > 50was truncated without warning.CLAUDE.md— guide for Claude Code sessions: layout, codex review pattern, release process, homebrew tap update steps.
Changed
--jsonflag rebuilt as a plainBool.--json-fieldskeeps comma-separated projection. Both registered viaaddJSONFlagsand markedMutuallyExclusive.cmd/actions.go—runandworkflowsubtrees converted from package-levelvars to factory functions (newRunCmd,newWorkflowCmd, ...).cmd/aliases.goshrank from 142 → 17 lines and now calls those same factories with aparentLabelparameter that disambiguates the alias variant. Result:diffoffj run list --helpflags vsfj actions run list --helpflags is now empty. Drift between the two paths is structurally impossible.fj apinow usesinternal/api.SharedHTTPClient(30s timeout, pooled connections) instead of a zero-value&http.Client{}with no timeout. A hung Forgejo no longer pins the CLI indefinitely.fj apiresponse body bounded byio.LimitReaderat 64 MB to prevent OOM-on-self.cmd/auth.goremoved redundant local--hostnamedeclarations on three subcommands. The persistent flag on rootCmd is now the only declaration; previously local declarations shadowed it, sofj --hostname=X auth loginandfj auth login --hostname=Xwent through different code paths.--tokenonauth loginemits a stderr warning when used (visible inps auxeand shell history). Flag not removed; just discoverable.- Error handling:
Hintis now a structured field onCLIError. JSON-error consumers get clean structure; the human renderer still appends\nHint: .... Dropped substring matching of"401"/"403"against rendered error strings (would match issue #403); now relies exclusively on typed*api.APIError. - Network errors (
no such host,connection refused,i/o timeout) return a structuredCLIErrorwith codeErrNetworkErrorand a hint. - Config dir created with mode 0700 instead of 0755.
Fixed
--config <path>now actually honored. Previously fed only into Viper; every command that touched config went throughinternal/config.Load()/Save()which always read the default path. Sofj --config other.yaml auth loginwrites to other.yaml now.fj run list --json,fj workflow list --json,fj wiki view --jsonnow produce JSON.cmd/aliases.goregistered--jsonasBoolbut handlers calledwantJSON()which doesGetString("json")— pflag returned a type-error thatwantJSONsilently swallowed.cmd/wiki.gohad the inverse bug (GetBoolagainst anaddJSONFlags-registered string flag). Both routed throughaddJSONFlags/wantJSON/outputJSONconsistently now.migrateConfigDiropens dst withO_TRUNC. Previously a partially- pre-existing dst file would have legacy contents overwrite a prefix and leave stale tail bytes — silent YAML/token corruption. Refactored close handling intocopyOneConfigFile.
Security
fj apiendpoint path traversal closed.fj api '/../admin/users'previously normalized throughhttp.NewRequesttohttps://host/admin/users— silently sending authenticated traffic to non-API paths. Endpoint is now parsed viaurl.Parse,..segments rejected, thenJoinPathonto the/api/v1base. URL-encoded%2E%2Eis also caught because Go decodes before our split.fj api --paginatevalidates same-origin before forwarding the bearer token to aLink: rel="next"URL. Refuses to reattachAuthorizationif the next URL's scheme isn'thttpsor its host doesn't match the configured one.initConfigwarns on stderr if the resolved config file is world or group readable (mode & 0o077 != 0).
0.3.0c - 2026-03-21
Added
Label Management
fj label list- List repository labelsfj label create- Create a label with color and descriptionfj label edit- Edit label name, color, or descriptionfj label delete- Delete a label
Milestone Management
fj milestone list- List milestones with state filteringfj milestone view- View milestone detailsfj milestone create- Create a milestone with description and due datefj milestone edit- Edit milestone title, description, due date, or statefj milestone delete- Delete a milestone
Wiki Management
fj wiki list- List wiki pagesfj wiki view- View wiki page contentfj wiki create- Create a wiki page from flag or filefj wiki edit- Edit a wiki pagefj wiki delete- Delete a wiki page
Issue Dependencies
fj issue edit --add-dependency <number>- Add issue dependencyfj issue edit --remove-dependency <number>- Remove issue dependency
0.3.0b - 2026-03-21
Added
Repository Management
fj repo edit- Edit repository settings (visibility, description, homepage, default branch)
Fixed
fj repo create --publicflag was defined but never read; now properly wired up
0.3.0a - 2026-03-21
Added
Raw API Access
fj api <endpoint>- Make authenticated REST API requests to any Forgejo/Gitea endpoint- HTTP method selection (
--method/-X), auto-switches to POST when fields are provided - JSON field assembly (
--field/-f) with type inference (bool, int, float, null, string) - Raw string fields (
--raw-field/-F) - Request body from file or stdin (
--input) - Custom headers (
--header/-H) - Path interpolation (
{owner},{repo}) from git context - Response header display (
--include/-i)
- HTTP method selection (
Pull Request Management
fj pr diff <number>- View the diff for a pull request- Colorized output (
--color auto/always/never) - Changed file names only (
--name-only) - Diffstat summary (
--stat)
- Colorized output (
fj pr comment <number>- Add a comment to a pull request- Body from flag (
--body/-b) or file (--body-file,-for stdin) - JSON output (
--json)
- Body from flag (
fj pr review <number>- Submit a review on a pull request- Approve (
--approve/-a), request changes (--request-changes/-r), or comment (--comment/-c) - Body from flag or file
- JSON output (
--json)
- Approve (
Agentic / Machine-Readable Output
--json-errorsglobal flag for structured JSON error output on stderr- Error codes:
auth_required,not_found,api_error,invalid_input,git_detection_failed,network_error - HTTP status code and detail included when available
- Automatic mapping of API errors (401/403 →
auth_required, 404 →not_found)
- Error codes:
0.3.0 - 2026-03-13
Added
Forgejo Actions
fj actions run watch <run-id>- Poll a run until completionfj actions run rerun <run-id>- Trigger a rerun of a workflow runfj actions run cancel <run-id>- Cancel an in-progress workflow runfj actions workflow enable <workflow>- Enable a workflowfj actions workflow disable <workflow>- Disable a workflow
Repository Management
fj repo create <name>- Create a new repository with full option set:--private/--public,--description,--add-readme,--gitignore,--license,--homepage,--clone,--team
Issue Management
fj issue create -l <label>- Assign labels when creating an issuefj issue edit --add-label/--remove-label- Add or remove labels on existing issuesfj issue close -c <comment>- Close an issue with an optional comment
Workflow Management
fj actions workflow list/view/run- List, view, and trigger workflows
Auth Helpers
fj auth token- Print the stored token for the current hostfj auth logout- Remove authentication for a host
Shell Completions and Man Pages
fj completion [bash|zsh|fish|powershell]- Generate shell completion scriptsfj manpages --dir <path>- Generate man pages for all commands
JSON Output
--jsonflag for all list and view commands: PRs, issues, releases, workflow runs, workflows
Fixed
- Respect
$XDG_CONFIG_HOMEfor config file location (was always using~/.config)
0.2.0 - 2026-01-09
Added
Release Management
fj release list- List releases for a repositoryfj release view- View details of a specific release (supports "latest" keyword)fj release create- Create new releases with optional asset uploadsfj release upload- Upload assets to existing releases with optional clobber supportfj release delete- Delete releases (preserves Git tags)
Issue Management
fj issue edit- Edit existing issues with support for updating title, body, and labels
Pull Request Management
fj pr create --assignee- Assign users when creating pull requests
Repository Detection
- Automatic hostname detection from git remote URLs
- Improved multi-instance support with auto-detection from git context
Improved
- Enhanced documentation with AUR and Homebrew installation instructions
- Added functional tests for release management and issue editing
- Added Makefile
installtarget for easier local installation - Added
.editorconfigfor consistent code formatting
Development
- CI: Added nightly builds for continuous testing
- Expanded functional test coverage for new features
0.1.0 - 2025-12-16
Added
Core Features
- Initial release of fj - Forgejo CLI tool
- Multi-instance support for any Forgejo/Gitea instance
- Automatic repository detection from git context (optional
-Rflag) - Secure authentication with personal access tokens
- Configuration management via
~/.config/fj/config.yaml
Pull Request Management
fj pr list- List pull requests with filtering by statefj pr view- View detailed pull request informationfj pr create- Create new pull requestsfj pr merge- Merge pull requests with configurable merge methods
Issue Management
fj issue list- List issues with state filteringfj issue view- View detailed issue informationfj issue create- Create new issuesfj issue comment- Add comments to issuesfj issue close- Close issues
Repository Operations
fj repo view- View repository detailsfj repo list- List user repositoriesfj repo clone- Clone repositories with protocol selection (HTTPS/SSH)fj repo fork- Fork repositories
Forgejo Actions Support
fj actions run list- List workflow runs with status and metadatafj actions run view- View detailed run information, jobs, and logs- Support for
--verbose,--log,--log-failed, and--jobflags
- Support for
fj actions secret list- List repository secretsfj actions secret create- Create repository secretsfj actions secret delete- Delete repository secretsfj actions variable list- List repository variablesfj actions variable get- Get variable valuesfj actions variable create- Create repository variablesfj actions variable update- Update repository variablesfj actions variable delete- Delete repository variables
Authentication
fj auth login- Interactive authentication with Forgejo instancesfj auth status- Check authentication status- Environment variable support (
FJ_HOST,FJ_TOKEN)
Development
- Comprehensive unit test suite
- Functional end-to-end tests
- CI/CD pipeline with automated testing
- Code quality checks and linting
Technical Details
- Built with Go 1.23+
- Uses Gitea SDK for API interactions
- Cobra framework for CLI structure
- Viper for configuration management