diff --git a/README.md b/README.md index f5d7814..39d5566 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,18 @@ Multi-host from day one. Tokens are stored in your OS keychain.

+

+ fj demo +

+ - + ## Install diff --git a/dist/v0.1.0/SHA256SUMS b/dist/v0.1.0/SHA256SUMS new file mode 100644 index 0000000..a2a3352 --- /dev/null +++ b/dist/v0.1.0/SHA256SUMS @@ -0,0 +1,2 @@ +eb5fd0206a5194179f6d1aecee7fe4a4a5434e1f44ed75a525f7f41d18670061 fj-v0.1.0-darwin-aarch64.tar.gz +d7102095f051f4af7af1d9dbf34678df85142fdfece71dcab0cc111aeb942c2c fj-v0.1.0-darwin-x86_64.tar.gz diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-aarch64.tar.gz b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64.tar.gz new file mode 100644 index 0000000..39f0e76 Binary files /dev/null and b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64.tar.gz differ diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/CHANGELOG.md b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/CHANGELOG.md new file mode 100644 index 0000000..c6f677e --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/CHANGELOG.md @@ -0,0 +1,121 @@ +# 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`. diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/LICENSE b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/LICENSE new file mode 100644 index 0000000..8e73da2 --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/README.md b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/README.md new file mode 100644 index 0000000..caf77a6 --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/README.md @@ -0,0 +1,149 @@ +# 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. + + + + +## 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-` 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 ` (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-` is invokable as `fj [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 diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/fj b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/fj new file mode 100755 index 0000000..d52a813 Binary files /dev/null and b/dist/v0.1.0/fj-v0.1.0-darwin-aarch64/fj differ diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-x86_64.tar.gz b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64.tar.gz new file mode 100644 index 0000000..755fea6 Binary files /dev/null and b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64.tar.gz differ diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/CHANGELOG.md b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/CHANGELOG.md new file mode 100644 index 0000000..c6f677e --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/CHANGELOG.md @@ -0,0 +1,121 @@ +# 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`. diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/LICENSE b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/LICENSE new file mode 100644 index 0000000..8e73da2 --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/README.md b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/README.md new file mode 100644 index 0000000..caf77a6 --- /dev/null +++ b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/README.md @@ -0,0 +1,149 @@ +# 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. + + + + +## 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-` 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 ` (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-` is invokable as `fj [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 diff --git a/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/fj b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/fj new file mode 100755 index 0000000..ff38aff Binary files /dev/null and b/dist/v0.1.0/fj-v0.1.0-darwin-x86_64/fj differ diff --git a/scripts/_demo-session.sh b/scripts/_demo-session.sh deleted file mode 100755 index 9815fe0..0000000 --- a/scripts/_demo-session.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash -# Drives an asciinema recording. Don't invoke directly; run record-demo.sh. - -set -u -PS1='\$ ' -export PS1 - -PAUSE_BETWEEN=0.6 -PAUSE_AFTER=1.2 - -say() { printf '\033[1;34m# %s\033[0m\n' "$*"; sleep "$PAUSE_BETWEEN"; } -do_() { printf '\033[1m$ %s\033[0m\n' "$*"; sleep "$PAUSE_BETWEEN"; eval "$@"; sleep "$PAUSE_AFTER"; } - -clear -say "fj: a CLI for Forgejo. Multi-host, tokens in the keychain." -do_ "fj --version" - -say "Inside a clone, no flags needed: fj infers the repo from your git remote." -do_ "fj repo view | head -8" - -say "Issues, PRs, releases all work the same way." -do_ "fj issue list --state all -L 5" -do_ "fj pr list --state all -L 5" - -say "The api escape hatch with a jq-ish projector." -do_ "fj api /version" -do_ "fj api /user -q .login" - -say "Selective JSON for scripting." -do_ "fj repo list -L 3 --json --json-fields full_name,private" - -say "Or just browse on the web." -say " fj browse src/main.rs" -sleep 1.5 - -clear -say "60+ subcommands. Try fj --help." -sleep 2 diff --git a/scripts/demo.tape b/scripts/demo.tape new file mode 100644 index 0000000..b2bba60 --- /dev/null +++ b/scripts/demo.tape @@ -0,0 +1,93 @@ +# vhs tape file for the fj README demo. +# +# Reproduce with: +# brew install vhs +# ./scripts/record-demo.sh +# +# The tape is the source of truth. Edit it, re-record, commit the +# updated assets/demo.gif and (optionally) assets/demo.mp4. +# +# Pre-requisites the recorder needs: +# * `fj` on PATH (build it via `cargo build --release` and symlink) +# * `fj auth login --host rasterhub.com` already completed +# * Run from inside the fj clone (so `fj repo view` resolves via the +# git remote) + +Output assets/demo.gif +Output assets/demo.mp4 + +Set Theme "Catppuccin Mocha" +Set FontSize 16 +Set Width 1100 +Set Height 720 +Set TypingSpeed 50ms +Set Padding 24 +Set PlaybackSpeed 1.0 +Set Shell zsh + +# Establish a clean prompt. +Hide +Type "clear" +Enter +Show +Sleep 600ms + +Type "fj --version" +Sleep 300ms +Enter +Sleep 1200ms + +Type "# inside a clone, fj infers the repo from the git remote" +Sleep 200ms +Enter +Sleep 600ms + +Type "fj repo view | head -10" +Sleep 200ms +Enter +Sleep 2200ms + +Type "# issues, PRs, releases — same shape" +Sleep 200ms +Enter +Sleep 500ms + +Type "fj issue list --state all -L 5" +Sleep 200ms +Enter +Sleep 2000ms + +Type "fj pr list --state all -L 5" +Sleep 200ms +Enter +Sleep 2200ms + +Type "# api escape hatch with jq-ish projection" +Sleep 200ms +Enter +Sleep 500ms + +Type "fj api /version" +Sleep 200ms +Enter +Sleep 1500ms + +Type "fj api /user -q .login" +Sleep 200ms +Enter +Sleep 1500ms + +Type "# gh-style selective JSON for scripts" +Sleep 200ms +Enter +Sleep 500ms + +Type "fj repo list -L 3 --json --json-fields full_name,private" +Sleep 200ms +Enter +Sleep 2800ms + +Type "fj --help | head -20" +Sleep 200ms +Enter +Sleep 3000ms