chore: gitignore release build artifacts and local Claude state
Some checks are pending
ci / check (push) Waiting to run

dist/v*/ holds tarballs/SHAs we upload to Forgejo releases, not source.
.claude/settings.local.json is per-machine allow-list state that
shouldn't travel with the repo.

Removes the artifacts that slipped into the previous commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stephen Way 2026-05-13 15:47:55 -07:00
parent 65420678d9
commit 61cfd85254
No known key found for this signature in database
12 changed files with 6 additions and 584 deletions

6
.gitignore vendored
View file

@ -6,3 +6,9 @@ Cargo.lock.bak
.vscode/ .vscode/
*.swp *.swp
*.swo *.swo
# Release build outputs (uploaded to Forgejo releases, never tracked)
/dist/v*/
# Local Claude / agent state
.claude/settings.local.json

View file

@ -1,2 +0,0 @@
eb5fd0206a5194179f6d1aecee7fe4a4a5434e1f44ed75a525f7f41d18670061 fj-v0.1.0-darwin-aarch64.tar.gz
d7102095f051f4af7af1d9dbf34678df85142fdfece71dcab0cc111aeb942c2c fj-v0.1.0-darwin-x86_64.tar.gz

Binary file not shown.

View file

@ -1,121 +0,0 @@
# Changelog
All notable changes will be recorded here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added (distribution + open-source ready)
- `LICENSE` (MIT) at the repo root. Cargo.toml had always declared MIT;
the file was just missing.
- `.forgejo/workflows/release.yml`: on `v*` tags, builds for
`darwin-aarch64`, `darwin-x86_64`, `linux-x86_64`; uploads tarballs,
`SHA256SUMS`, and a pre-rendered `fj.rb` to the Forgejo release.
- Homebrew formula template at `dist/homebrew/fj.rb.tmpl` and
`scripts/render-homebrew-formula.sh` to fill SHA256s post-release.
Publishes into the existing `rasterandstate/homebrew-tap`.
- `.forgejo/issue_template/{bug,feature,api-gap}.md` and
`.forgejo/pull_request_template.md` to keep triage cheap.
- `scripts/record-demo.sh` + `scripts/_demo-session.sh` to record an
asciinema demo; README has a placeholder embed for the v0.1.0 cast.
- `docs/compatibility.md`: tested Forgejo versions, caveats for older
Gitea, and Forgejo-only endpoints.
- One-shot version probe during `fj auth login` that warns when the
server reports a pre-7.x version (with tests for the parser).
### Added (agent-focused Forgejo gaps)
- `fj issue edit-comment` / `delete-comment`. Lets an agent (or you)
fix or remove a wrong comment after the fact.
- `fj search code "..."` (and `-R owner/name` to scope to one repo).
Powered by Forgejo's `/repos/search/code` endpoint.
- `fj pr request-review N user1 user2,user3` and
`fj pr unrequest-review N user1`. Distinct from `pr review`, which
submits your own review.
- `fj repo watch` / `unwatch` / `star` / `unstar` / `starred`.
- `fj milestone {list,view,create,edit,close,reopen,delete,assign}`.
Includes `fj milestone assign N --milestone ID|none` to attach an
issue or PR to a milestone.
### Added (UX + stability)
- `--json-fields field1,field2` global flag. gh-style projection on top
of any `--json` output, with dotted-path support
(`--json-fields owner.login,id`).
- 429 / Retry-After honored in the retry loop with a 30 s cap. Wiremock
test added.
- `did you mean` suggestions on typo'd subcommands via clap's
`suggestions` feature.
- `fj auth token` and `fj auth status --show-token` now refuse to write
to a TTY (use `--force` to override). Avoids accidental shoulder-
surfing or capture in shell history.
- `tokio::signal::ctrl_c()` race in `cli::run` so the pager guard drops
cleanly on SIGINT.
- 10 wiremock-backed HTTP client integration tests covering retry
behavior (5xx, 429), header forwarding, pagination, and panic-free
error paths.
- `Client::for_base_url` test constructor pointing at an arbitrary URL.
- `.forgejo/workflows/ci.yml` runs the same gate as the pre-push hook
on every push and PR.
### Added (docs)
- `SECURITY.md` covering threat model, known sharp edges, and reporting.
- `docs/gh-to-fj.md` — complete command-by-command mapping.
- `docs/faq.md` — common questions about tokens, hosts, debug,
scripting, plugins.
### Changed
- Trimmed dependencies (no more `indicatif`, `futures-util`,
`is-terminal`, `textwrap`, `tempfile` in prod). Dropped reqwest
features we don't use (`stream`, `brotli`). Release profile uses
`lto = "fat"` and `panic = "abort"`.
- HTTP retry loop builds the request once and clones via
`reqwest::Request::try_clone` per attempt.
- Binary size: 5.94 MB → 4.15 MB stripped (-30%).
### Fixed
- **Shell injection** in `fj auth setup-git`. The hostname now must
match a strict DNS pattern before being interpolated into the
credential-helper string, and we call `git config` directly with
separate args instead of going through `sh -c`.
- **Pager won't compile on Windows**. The libc-based `dup2` redirect
now lives behind `#[cfg(unix)]`; non-Unix gets a no-op stub that
returns `None` from `maybe_start`.
- Removed the unsafe `std::env::set_var("FJ_NO_PAGER")` from dispatch.
`--no-pager` is now threaded into `pager::maybe_start(force_disabled)`.
- Replaced the panicking `.expect("token contains invalid header chars")`
in `auth_headers` with a typed error.
## 0.1.0 — 2026-05-13
Initial release. Multi-host Forgejo CLI with feature parity to `gh`
across the surface Forgejo exposes. Commands:
- `auth`: login, status, logout, list, switch, token, refresh, setup-git
- `repo`: list, view, clone, create, fork, sync, edit, rename, archive,
unarchive, delete, branches, topics, mirror, mirror-sync
- `issue`: list, view, create, edit, close, reopen, comment, develop
- `pr`: list, view, create, edit, diff, commits, files, checks, ready,
review, status, checkout, merge, close, reopen
- `release`: list, view, create, edit, delete, upload, download
- `label`, `run`, `secret`, `variable`, `search`, `browse`, `status`,
`org`, `ssh-key`, `gpg-key`, `alias`, `config`, `protect`, `hook`,
`extension`, `gist`, `api`, `completion`, `man`
Other highlights:
- Repo auto-detection from `upstream` / `origin` git remote.
- `--web` flag on all list/view subcommands.
- `$EDITOR` integration for body inputs.
- `fj api` with `-H`, `-X`, `-f`, `-F`, `--paginate`, `--include`,
`--silent`, `--jq` (dot-paths, `[N]`/`[-N]`, pipes).
- `--debug` / `FJ_DEBUG` request logging.
- Tokens in the OS keychain.
- Pager via `dup2` redirect to `$FJ_PAGER` / `$PAGER` / `less -FRX`.
- Pre-push hook running fmt, clippy `-D warnings`, tests, and release
build before any push. Live API smoke gated on `FJ_E2E=1`.

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 Stephen Way
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,149 +0,0 @@
# 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.
<!--
TODO: replace the line below with an asciinema embed once the v0.1.0
release is tagged. Run `./scripts/record-demo.sh` then
`asciinema upload dist/demo.cast` and paste the returned URL.
-->
<!-- [![asciicast](https://asciinema.org/a/REPLACE.svg)](https://asciinema.org/a/REPLACE) -->
## Install
```sh
# Homebrew (macOS + Linux):
brew tap rasterandstate/tap
brew install fj
# From source:
cargo install --path .
# or
cargo build --release && cp target/release/fj ~/.local/bin/fj
```
## Quick start
```sh
fj auth login # add a host and token
fj auth status # show signed-in hosts
fj repo list # repos you own
fj repo view owner/name # repo overview
fj issue list -R owner/name # issues
fj pr list -R owner/name --state open # pull requests
fj api /repos/search -X GET -f q=foo # raw API escape hatch
```
`-R/--repo` is optional inside a git clone. fj detects the upstream from
`upstream`, then `origin`, then any other remote.
## Commands
| Group | Common operations |
| ---------- | --------------------------------------------------------------------------------- |
| `auth` | login, status, logout, list, switch, token, refresh, setup-git |
| `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 |
| `release` | list, view, create, edit, delete, upload, download |
| `label` | list, create, edit, delete |
| `milestone`| list, view, create, edit, close, reopen, delete, assign |
| `run` | list, view, rerun, cancel (Forgejo Actions workflow runs) |
| `secret` | list, set, delete (Actions secrets) |
| `variable` | list, set, delete (Actions variables) |
| `search` | repos, issues, prs, users, code |
| `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.
- `--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.
## Config
- 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
cargo build --release # ~4 MB stripped binary at target/release/fj
./target/release/fj completion zsh > ~/.zfunc/_fj
./target/release/fj man -o ~/man/man1
```
## 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
## License
MIT

Binary file not shown.

Binary file not shown.

View file

@ -1,121 +0,0 @@
# Changelog
All notable changes will be recorded here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added (distribution + open-source ready)
- `LICENSE` (MIT) at the repo root. Cargo.toml had always declared MIT;
the file was just missing.
- `.forgejo/workflows/release.yml`: on `v*` tags, builds for
`darwin-aarch64`, `darwin-x86_64`, `linux-x86_64`; uploads tarballs,
`SHA256SUMS`, and a pre-rendered `fj.rb` to the Forgejo release.
- Homebrew formula template at `dist/homebrew/fj.rb.tmpl` and
`scripts/render-homebrew-formula.sh` to fill SHA256s post-release.
Publishes into the existing `rasterandstate/homebrew-tap`.
- `.forgejo/issue_template/{bug,feature,api-gap}.md` and
`.forgejo/pull_request_template.md` to keep triage cheap.
- `scripts/record-demo.sh` + `scripts/_demo-session.sh` to record an
asciinema demo; README has a placeholder embed for the v0.1.0 cast.
- `docs/compatibility.md`: tested Forgejo versions, caveats for older
Gitea, and Forgejo-only endpoints.
- One-shot version probe during `fj auth login` that warns when the
server reports a pre-7.x version (with tests for the parser).
### Added (agent-focused Forgejo gaps)
- `fj issue edit-comment` / `delete-comment`. Lets an agent (or you)
fix or remove a wrong comment after the fact.
- `fj search code "..."` (and `-R owner/name` to scope to one repo).
Powered by Forgejo's `/repos/search/code` endpoint.
- `fj pr request-review N user1 user2,user3` and
`fj pr unrequest-review N user1`. Distinct from `pr review`, which
submits your own review.
- `fj repo watch` / `unwatch` / `star` / `unstar` / `starred`.
- `fj milestone {list,view,create,edit,close,reopen,delete,assign}`.
Includes `fj milestone assign N --milestone ID|none` to attach an
issue or PR to a milestone.
### Added (UX + stability)
- `--json-fields field1,field2` global flag. gh-style projection on top
of any `--json` output, with dotted-path support
(`--json-fields owner.login,id`).
- 429 / Retry-After honored in the retry loop with a 30 s cap. Wiremock
test added.
- `did you mean` suggestions on typo'd subcommands via clap's
`suggestions` feature.
- `fj auth token` and `fj auth status --show-token` now refuse to write
to a TTY (use `--force` to override). Avoids accidental shoulder-
surfing or capture in shell history.
- `tokio::signal::ctrl_c()` race in `cli::run` so the pager guard drops
cleanly on SIGINT.
- 10 wiremock-backed HTTP client integration tests covering retry
behavior (5xx, 429), header forwarding, pagination, and panic-free
error paths.
- `Client::for_base_url` test constructor pointing at an arbitrary URL.
- `.forgejo/workflows/ci.yml` runs the same gate as the pre-push hook
on every push and PR.
### Added (docs)
- `SECURITY.md` covering threat model, known sharp edges, and reporting.
- `docs/gh-to-fj.md` — complete command-by-command mapping.
- `docs/faq.md` — common questions about tokens, hosts, debug,
scripting, plugins.
### Changed
- Trimmed dependencies (no more `indicatif`, `futures-util`,
`is-terminal`, `textwrap`, `tempfile` in prod). Dropped reqwest
features we don't use (`stream`, `brotli`). Release profile uses
`lto = "fat"` and `panic = "abort"`.
- HTTP retry loop builds the request once and clones via
`reqwest::Request::try_clone` per attempt.
- Binary size: 5.94 MB → 4.15 MB stripped (-30%).
### Fixed
- **Shell injection** in `fj auth setup-git`. The hostname now must
match a strict DNS pattern before being interpolated into the
credential-helper string, and we call `git config` directly with
separate args instead of going through `sh -c`.
- **Pager won't compile on Windows**. The libc-based `dup2` redirect
now lives behind `#[cfg(unix)]`; non-Unix gets a no-op stub that
returns `None` from `maybe_start`.
- Removed the unsafe `std::env::set_var("FJ_NO_PAGER")` from dispatch.
`--no-pager` is now threaded into `pager::maybe_start(force_disabled)`.
- Replaced the panicking `.expect("token contains invalid header chars")`
in `auth_headers` with a typed error.
## 0.1.0 — 2026-05-13
Initial release. Multi-host Forgejo CLI with feature parity to `gh`
across the surface Forgejo exposes. Commands:
- `auth`: login, status, logout, list, switch, token, refresh, setup-git
- `repo`: list, view, clone, create, fork, sync, edit, rename, archive,
unarchive, delete, branches, topics, mirror, mirror-sync
- `issue`: list, view, create, edit, close, reopen, comment, develop
- `pr`: list, view, create, edit, diff, commits, files, checks, ready,
review, status, checkout, merge, close, reopen
- `release`: list, view, create, edit, delete, upload, download
- `label`, `run`, `secret`, `variable`, `search`, `browse`, `status`,
`org`, `ssh-key`, `gpg-key`, `alias`, `config`, `protect`, `hook`,
`extension`, `gist`, `api`, `completion`, `man`
Other highlights:
- Repo auto-detection from `upstream` / `origin` git remote.
- `--web` flag on all list/view subcommands.
- `$EDITOR` integration for body inputs.
- `fj api` with `-H`, `-X`, `-f`, `-F`, `--paginate`, `--include`,
`--silent`, `--jq` (dot-paths, `[N]`/`[-N]`, pipes).
- `--debug` / `FJ_DEBUG` request logging.
- Tokens in the OS keychain.
- Pager via `dup2` redirect to `$FJ_PAGER` / `$PAGER` / `less -FRX`.
- Pre-push hook running fmt, clippy `-D warnings`, tests, and release
build before any push. Live API smoke gated on `FJ_E2E=1`.

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 Stephen Way
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,149 +0,0 @@
# 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.
<!--
TODO: replace the line below with an asciinema embed once the v0.1.0
release is tagged. Run `./scripts/record-demo.sh` then
`asciinema upload dist/demo.cast` and paste the returned URL.
-->
<!-- [![asciicast](https://asciinema.org/a/REPLACE.svg)](https://asciinema.org/a/REPLACE) -->
## Install
```sh
# Homebrew (macOS + Linux):
brew tap rasterandstate/tap
brew install fj
# From source:
cargo install --path .
# or
cargo build --release && cp target/release/fj ~/.local/bin/fj
```
## Quick start
```sh
fj auth login # add a host and token
fj auth status # show signed-in hosts
fj repo list # repos you own
fj repo view owner/name # repo overview
fj issue list -R owner/name # issues
fj pr list -R owner/name --state open # pull requests
fj api /repos/search -X GET -f q=foo # raw API escape hatch
```
`-R/--repo` is optional inside a git clone. fj detects the upstream from
`upstream`, then `origin`, then any other remote.
## Commands
| Group | Common operations |
| ---------- | --------------------------------------------------------------------------------- |
| `auth` | login, status, logout, list, switch, token, refresh, setup-git |
| `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 |
| `release` | list, view, create, edit, delete, upload, download |
| `label` | list, create, edit, delete |
| `milestone`| list, view, create, edit, close, reopen, delete, assign |
| `run` | list, view, rerun, cancel (Forgejo Actions workflow runs) |
| `secret` | list, set, delete (Actions secrets) |
| `variable` | list, set, delete (Actions variables) |
| `search` | repos, issues, prs, users, code |
| `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.
- `--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.
## Config
- 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
cargo build --release # ~4 MB stripped binary at target/release/fj
./target/release/fj completion zsh > ~/.zfunc/_fj
./target/release/fj man -o ~/man/man1
```
## 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
## License
MIT

Binary file not shown.