A CLI-first git forge.

cli forge git self-hosted

https://gitbay.org

Wiki: Parity

Parity

Parity

Which surface can do what. The CLI is meant to be the complete interface: every capability exists over SSH, and the other surfaces dispatch the same control commands rather than reimplementing them, so they cannot drift. This page is updated in the merge request that changes a row.

Three surfaces now: the CLI over SSH, the web, and the iOS client (krz/gitbay-ios). A no in the cli column is a defect, not a preference — it means some surface reached around the registry and stranded a capability where only it can reach.

Rule

A capability lands over SSH first. If it belongs to the triage/review/respond loop, it lands on the web in the same merge request. Anything whose input is a credential — secrets, mirror tokens, API tokens, session minting — stays SSH-only by design: the web dispatcher refuses SSHOnly commands outright.

Rows are one page or one action each. Grouped rows hide gaps, twice now: "browse, log, blame, search" read as covered while blame had no command at all, and "build list, log" read as covered while the job list a trigger can name had none (krz/gitbay#50), leaving the picker browser-only and the iOS build screen unable to say more than the log.

Merge requests

capability cli web ios
read, diff, commits yes yes yes
comment yes yes yes
edit title and body yes yes yes
review (approve etc.) yes yes yes
resolve a thread yes yes yes
comment on a diff line yes yes yes
merge (all strategies) yes yes yes
close yes yes yes
create yes yes yes
create from a fork yes no yes
retarget yes yes no
milestone yes yes yes
choose body markup yes no no

Creating from a fork works anywhere the source can be typed as owner/name:branch; only the web lacks it. Retargeting moves an open merge request onto another branch of the same repository and stales the reviews, since an approval was of the diff against the old branch.

Issues

capability cli web ios
read, list, filter yes yes yes
create yes yes yes
comment yes yes yes
edit title and body yes yes yes
close and reopen yes yes yes
labels, assignees yes yes yes
milestone yes yes yes
milestone list yes yes yes
choose body markup yes no no

Issue, MR and release bodies, and their comments, carry the markup they were written in — --format md|org on create, comment and edit, stored alongside the text so changing a preference later cannot reinterpret prose that already exists. Every surface renders the stored format; the no above is the absence of a picker on the web form and in the iOS composer, both of which write markdown. Diff-line comments have no format column and are always markdown.

Repositories

capability cli web ios
browse files yes yes yes
read a file yes yes yes
commit log yes yes yes
commit log at a ref yes yes yes
one commit with its patch yes yes yes
blame yes yes yes
search file contents yes yes yes
branches and tags yes yes yes
wiki (read) yes yes yes
download an archive yes yes n/a
edit a file yes yes yes
create yes yes yes
pin yes yes yes
settings, protection yes yes yes
topics, website yes yes yes
visibility yes yes yes
archive (read-only flag) yes yes yes
release list, show yes yes yes
release create, edit yes yes yes
build list yes yes yes
build show (one build) yes yes yes
build log yes yes yes
build jobs yes yes yes
build trigger yes yes yes
delete, transfer yes no no
release delete yes no no

No row is web-only any more. Blame, file editing, log at a ref, archive, the public listing and the wiki were all in that state — a handler reading git or the store directly instead of dispatching a command — until krz/gitbay!99, !101 and !102 gave them commands.

The wiki row covers reading. Editing a wiki is a push to <repo>.wiki.git on every surface, including the web, so there is no edit row to have parity on.

n/a marks a capability deliberately absent from a surface rather than missing from it. Archive download is n/a on iOS: the read API carries a command's stdout as a JSON string, so a gzip stream cannot survive it, and the app has nowhere useful to put a tarball — the brief rules out local git, so there is no clone, checkout or build to feed. The web's route stays the way to get one.

A README or wiki page's org renders per surface: the web through go-org, the iOS client through the shared OrgSwift package (krz/org-swift). OrgSwift is held to orgo's output by the krz/org-conformance corpus — golden renderings from orgo, itself diffed against Emacs ox-html — so constructs the iOS client used to approximate (tables, footnotes, timestamps, heading tags, nested lists) now render the way the reference does. go-org is not yet on the corpus.

Discovery

capability cli web ios
search repositories yes yes yes
browse all public repositories yes yes yes
profile page yes yes yes
profile about and links yes yes no
activity feed yes yes yes

explore is the listing without a query; repo search is the one with.

About text renders as markdown or org-mode per the about_format it was stored with. The iOS Profile decoder lists its keys explicitly, so it ignores about and links rather than breaking on them.

Accounts

capability cli web ios
SSH keys: list, add, remove yes yes yes
PGP keys: list, add, remove yes yes yes
email add and verify yes yes yes
dashboard aggregate yes yes yes
API token mint yes no no
account export bundle yes no no
profile set yes no no

profile set carries description, website, about and links. It is not SSHOnly — nothing about a bio is a credential, and the JSON API runs it — but no surface has ever offered a form, so the no above is missing UI rather than a rule.

Organizations

capability cli web ios
read members and teams yes yes yes
members add, remove, role yes yes yes
teams create, delete yes yes yes
team members yes yes yes
team repo grants yes yes yes
create, rename, delete yes no no

Pagination

issue list, mr list, repo list, and feed take --limit <n> and --cursor <c>. Cursors are opaque; each page carries the next one. Without the flags a list stays complete, so existing scripts are unchanged. The web renders server-side and does not paginate; iOS pages with the cursors.

SSH only, by design

Build secrets, mirror configuration and tokens, custom domain claims, API token minting, web session minting, deploy keys, account and instance administration. Deleting or transferring a repository is also CLI-only: both want a typed confirmation, not a button.

These are the only rows where a no is intended. Everywhere else a no is work outstanding, and n/a means a surface cannot usefully carry the capability at all — see the archive note above.