gclo clones and updates every repository of a GitHub organization or account. This adds Gitea (and servers that speak its API, such as Forgejo) beside GitHub: an account names a forge and, for Gitea, the server it lives on.
Planned for 1.2.0. Nothing of it merges before 1.1.1 is tagged (#200).
What a user gets
An account can be a GitHub account (as today) or a Gitea account with a server address, in the desktop app's wizard and in gclo accounts.
gclo sync, gclo repos and gclo orgs take --forge gitea --server https://git.example.com.
Everything after the listing is the same: clone, fast-forward, path recovery, Sync all.
Constraints (decided)
No new dependency. The Gitea API is called with HttpClient and source-generated JSON, and tested offline through a fake handler, so nothing needs a coverage exclusion.
HTTPS only, and no way to switch certificate validation off.
The token is sent only to the server the account names: API requests go to that server and are never redirected; clone URLs are built from the account's server address, not taken from what the server says.
A server address typed by a user is new attack surface: an ADR and a threat-model update come with the first change.
README.md and docs/CLI.md move with the behaviour.
Steps (each its own pull request, in this order)
Engine: a forge-neutral failure type (ForgeAccessException, ForgeAccessKind; the GitHub type derives from it), ForgeKind, validation of a server address, the Gitea listers with a lister contract test suite, ADR, threat model. (#202)
Accounts and command line:Account.Forge and Account.Server (left out of the file when default, so old files read as before and old versions read new GitHub accounts), one place that builds the listers for an account, --forge and --server, default token and environment variable per forge, docs/CLI.md.
Desktop app: the wizard's forge and server step, forge-specific help texts and links, the workspace page, a second offline fixture organization for the UI suite, README.
Facts about the Gitea API this relies on
The server caps the page size whatever is asked for: page until an empty page (a short page does not end the list).
/orgs/{name}/repos is 404 for a user account; /user/orgs items carry username.
To confirm against a live server before step 2 is merged: git over HTTPS accepts the token as the password with any user name (the form gclo uses for GitHub).
gclo clones and updates every repository of a GitHub organization or account. This adds Gitea (and servers that speak its API, such as Forgejo) beside GitHub: an account names a forge and, for Gitea, the server it lives on.
Planned for 1.2.0. Nothing of it merges before 1.1.1 is tagged (#200).
## What a user gets
- An account can be a GitHub account (as today) or a Gitea account with a server address, in the desktop app's wizard and in `gclo accounts`.
- `gclo sync`, `gclo repos` and `gclo orgs` take `--forge gitea --server https://git.example.com`.
- Everything after the listing is the same: clone, fast-forward, path recovery, Sync all.
## Constraints (decided)
- **No new dependency.** The Gitea API is called with `HttpClient` and source-generated JSON, and tested offline through a fake handler, so nothing needs a coverage exclusion.
- **HTTPS only**, and **no way to switch certificate validation off**.
- **The token is sent only to the server the account names**: API requests go to that server and are never redirected; clone URLs are built from the account's server address, not taken from what the server says.
- A server address typed by a user is new attack surface: an ADR and a threat-model update come with the first change.
- `README.md` and `docs/CLI.md` move with the behaviour.
## Steps (each its own pull request, in this order)
1. **Engine:** a forge-neutral failure type (`ForgeAccessException`, `ForgeAccessKind`; the GitHub type derives from it), `ForgeKind`, validation of a server address, the Gitea listers with a lister contract test suite, ADR, threat model. (#202)
2. **Accounts and command line:** `Account.Forge` and `Account.Server` (left out of the file when default, so old files read as before and old versions read new GitHub accounts), one place that builds the listers for an account, `--forge` and `--server`, default token and environment variable per forge, `docs/CLI.md`.
3. **Desktop app:** the wizard's forge and server step, forge-specific help texts and links, the workspace page, a second offline fixture organization for the UI suite, README.
## Facts about the Gitea API this relies on
- The server caps the page size whatever is asked for: page until an empty page (a short page does not end the list).
- `/orgs/{name}/repos` is 404 for a user account; `/user/orgs` items carry `username`.
- Repository objects carry `name`, `full_name`, `default_branch`, `archived`, `empty`, `mirror`.
- To confirm against a live server before step 2 is merged: git over HTTPS accepts the token as the password with any user name (the form gclo uses for GitHub).
A decision made in step 2 after its review: accounts on another forge are kept in accounts-forges.json, not in accounts.json, because an older gclo rewrites accounts.json with the fields it knows (ADR 0010).
Still to confirm against a live server before step 2 merges: that Gitea takes the token as the git password with the fixed user name the git client uses, and what a token without read:organization gets from an organization's repository list.
State on 2026-11-11. All three steps are written, each as a pull request stacked on the one before; none merges before 1.1.1 is tagged (#200).
| Step | Issue | Pull request | State |
| --- | --- | --- | --- |
| 1. Engine listers | #202 | #203 | reviewed, fixes pushed |
| 2. Accounts and the command line | #204 | #205 | reviewed, fixes pushed (`8d855cd`), a review of that change alone is running |
| 3. The app's Add account wizard | #206 | #207 | open, gates pass, review running |
A decision made in step 2 after its review: accounts on another forge are kept in `accounts-forges.json`, not in `accounts.json`, because an older gclo rewrites `accounts.json` with the fields it knows (ADR 0010).
Still to confirm against a live server before step 2 merges: that Gitea takes the token as the git password with the fixed user name the git client uses, and what a token without `read:organization` gets from an organization's repository list.
Order of merging once 1.1.1 is tagged (#200): #203, then #205 (retargeted to main), then #207. Before #205 merges: the confirmation against a live Gitea server (the token as the git password with the user name the git client uses; what a token without read:organization gets from an organization's repository list). Follow-ups filed: #208, and notes on #190, #191, #192.
Update, 2026-11-11 (later): all three pull requests are reviewed and their findings fixed.
| Step | Pull request | Reviews | Tip |
| --- | --- | --- | --- |
| 1. Engine listers | #203 | one round, fixed | `bce029d` |
| 2. Accounts and the command line | #205 | three rounds; the last found no defect in the code | `04b458d` |
| 3. The app's Add account wizard | #207 | one round, fixed | `6deda64` |
Order of merging once 1.1.1 is tagged (#200): #203, then #205 (retargeted to `main`), then #207. Before #205 merges: the confirmation against a live Gitea server (the token as the git password with the user name the git client uses; what a token without `read:organization` gets from an organization's repository list). Follow-ups filed: #208, and notes on #190, #191, #192.
Update, 2026-11-11 (after the owner tried the build): GitHub and Gitea are to be equal options throughout, so three more steps were added on top of #207.
Update, 2026-11-11 (after the owner tried the build): GitHub and Gitea are to be equal options throughout, so three more steps were added on top of #207.
| Step | Issue | Pull request | State |
| --- | --- | --- | --- |
| 4. Quick Sync and the start screen | #209, #213 | #210 | reviewed, fixes pushed |
| 6. Version 1.2.0 and wording | #211 | #214 | open |
| 5. A default token per forge (Settings) | #212 | #215 | open, review running |
Order of merging once 1.1.1 is tagged (#200): #203, #205, #207, #210, #214, #215.
All six steps are merged into main (d5d4f67): #203 engine listers, #205 accounts and command line, #207 the Add account wizard, #210 Quick Sync and the start page, #214 version 1.2.0 and wording, #215 a default token per forge. A live run against git.kof22.com listed organizations and repositories and cloned and updated a private repository (details on #200). Left as their own issues: #208 (the command line cannot end a name clash by itself) and #216 (one window per data folder). Closing this one.
All six steps are merged into main (d5d4f67): #203 engine listers, #205 accounts and command line, #207 the Add account wizard, #210 Quick Sync and the start page, #214 version 1.2.0 and wording, #215 a default token per forge. A live run against git.kof22.com listed organizations and repositories and cloned and updated a private repository (details on #200). Left as their own issues: #208 (the command line cannot end a name clash by itself) and #216 (one window per data folder). Closing this one.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
gclo clones and updates every repository of a GitHub organization or account. This adds Gitea (and servers that speak its API, such as Forgejo) beside GitHub: an account names a forge and, for Gitea, the server it lives on.
Planned for 1.2.0. Nothing of it merges before 1.1.1 is tagged (#200).
What a user gets
gclo accounts.gclo sync,gclo reposandgclo orgstake--forge gitea --server https://git.example.com.Constraints (decided)
HttpClientand source-generated JSON, and tested offline through a fake handler, so nothing needs a coverage exclusion.README.mdanddocs/CLI.mdmove with the behaviour.Steps (each its own pull request, in this order)
ForgeAccessException,ForgeAccessKind; the GitHub type derives from it),ForgeKind, validation of a server address, the Gitea listers with a lister contract test suite, ADR, threat model. (#202)Account.ForgeandAccount.Server(left out of the file when default, so old files read as before and old versions read new GitHub accounts), one place that builds the listers for an account,--forgeand--server, default token and environment variable per forge,docs/CLI.md.Facts about the Gitea API this relies on
/orgs/{name}/reposis 404 for a user account;/user/orgsitems carryusername.name,full_name,default_branch,archived,empty,mirror.State on 2026-11-11. All three steps are written, each as a pull request stacked on the one before; none merges before 1.1.1 is tagged (#200).
8d855cd), a review of that change alone is runningA decision made in step 2 after its review: accounts on another forge are kept in
accounts-forges.json, not inaccounts.json, because an older gclo rewritesaccounts.jsonwith the fields it knows (ADR 0010).Still to confirm against a live server before step 2 merges: that Gitea takes the token as the git password with the fixed user name the git client uses, and what a token without
read:organizationgets from an organization's repository list.Update, 2026-11-11 (later): all three pull requests are reviewed and their findings fixed.
bce029d04b458d6deda64Order of merging once 1.1.1 is tagged (#200): #203, then #205 (retargeted to
main), then #207. Before #205 merges: the confirmation against a live Gitea server (the token as the git password with the user name the git client uses; what a token withoutread:organizationgets from an organization's repository list). Follow-ups filed: #208, and notes on #190, #191, #192.Update, 2026-11-11 (after the owner tried the build): GitHub and Gitea are to be equal options throughout, so three more steps were added on top of #207.
Order of merging once 1.1.1 is tagged (#200): #203, #205, #207, #210, #214, #215.
All six steps are merged into main (
d5d4f67): #203 engine listers, #205 accounts and command line, #207 the Add account wizard, #210 Quick Sync and the start page, #214 version 1.2.0 and wording, #215 a default token per forge. A live run against git.kof22.com listed organizations and repositories and cloned and updated a private repository (details on #200). Left as their own issues: #208 (the command line cannot end a name clash by itself) and #216 (one window per data folder). Closing this one.