Members and teams
Roles
Every org member has exactly one org-level role.
| Role | What they can do |
|---|---|
| Owner | Full org admin: manage billing, configure SSO and SCIM, manage security policy, invite and remove members, create and delete repositories, access all repository settings, view audit log |
| Member | Access repositories they have been granted access to; create new repositories (if the org policy permits); no access to org admin settings |
| Reader | Read-only access to repositories they have been granted access to — clone, browse, read issues and pull requests. Cannot push, create repositories, or reach org admin settings. Readers do not consume a billable seat — see Free readers below |
| Guest | Read-only, but scoped to specific repositories rather than the whole org. Same abilities as a Reader on the repos they are given. Free — Guests do not consume a billable seat |
| Collaborator | Write access scoped to specific repositories. Can push, and open and close issues and pull requests, on those repos only. No org admin access. Consumes a billable seat |
An org must have at least one Owner at all times. You cannot remove or demote the last Owner.
How a seat is decided
One rule covers every role above:
You occupy a billable seat if you can write somewhere. If everything you hold is read-only — or you hold nothing — you are free.
That is decided by the permission your teams grant, not by their names. So a read-only team you create yourself is free at any scope, and renaming a team never changes what you pay. Owners, Members and Collaborators can write, so they are billable; Readers and Guests cannot, so they are not.
Inviting members
Member management lives in the fremforge admin UI at /<org>/_admin/members — the Members page lists every current member with per-member Manage drawers and an Invite dialog at the top. Forgejo’s native frem.sh/org/<org>/teams page remains available as a fallback when you need to compose finer-grained team permissions; the in-product page covers the day-to-day invite / role / remove flow.
- Go to Org admin → Members (
/<org>/_admin/members). - Click Invite member.
- Enter the invitee’s username or email address and pick a role.
- Click Send invitation.
The invitee receives an email from noreply@frem.sh with an accept link. The link is valid for 72 hours (Forgejo-managed). If it expires, re-send it from the Pending invitations section on the same page.
In the Pending invitations section, the invitee appears as Pending until they accept. Pending members:
- Cannot access any org resource.
- Do not count as a billable seat until they accept the invitation.
- Can be cancelled at any time by removing them from the team while still pending.
Once the invitee accepts, their status changes to Active and they are added to the billable seat count at the next billing cycle. Activity is not required, acceptance is what counts.
Free readers (read-only, no billable seat)
A Reader has read-only access to the repositories they’re granted — clone, browse code, read issues and pull requests — but cannot push, create repositories, or reach org admin settings. Readers are free: they do not count against your seat cap and are never billed. Add as many as you like — auditors, stakeholders, contractors who only need to look, read-only dashboards, and so on.
Under the hood a Reader is a member of the org’s canonical Viewers team and of no team that grants write. Seat counting follows the permission a team grants, not its name: hold nothing but read-only teams and you are free; hold write anywhere and you are billed. (If you add someone to Viewers and Members, they are billed — write wins.)
Because the rule is permission-based rather than name-based, a read-only team you create yourself — Auditors, Stakeholders, whatever you call it — is also free, and scoping it to a handful of repositories does not change that. Use Guests when you want exactly that: free read, on chosen repositories.
Add a reader
Any of these work; the in-product path is the simplest:
- From the Members page (recommended). Go to Org admin → Members (
/<org>/_admin/members) → Invite member → enter the email → in Team(s), select Viewers (and nothing else) → Send invitation. When they accept, they join as a free reader. - Convert an existing member. Open the member’s Manage drawer and move them to Viewers (remove them from Members/Owners). They drop out of the billable seat count at the next billing cycle.
- Automatically via SSO. Map an identity-provider group to the Viewers team (see SSO and SCIM). Everyone in that group is provisioned as a free reader — no per-person invite needed.
- Forgejo-native fallback.
frem.sh/org/<org>/teams→ Viewers → Add team member. Use this only when you need finer team composition; the Members page covers the normal case.
Free readers are counted separately from paid seats in your billing summary (Org admin → Billing) and in the seats API, so you can always see how many free readers you have versus how many billable seats you’re using.
Not the same as a docs-only reader. If you want someone who can read your published docs but has no repository access and no Forgejo account at all, don’t add them to Viewers — instead give their SSO group an empty group→team mapping. See Wiki and public docs. A Reader (Viewers team) does get a Forgejo account and read access to granted repos; a docs-only reader does not.
Guests (free read, specific repositories)
A Reader can read every repository in the org. A Guest reads only the repositories you choose. Both are free — reading never costs a seat, whatever its scope.
Use Guests for a contractor reviewing one service, an auditor who needs two repositories rather than forty, or a partner team you want to keep out of everything else. It is the least-privilege version of a Reader, and it costs the same: nothing.
Guests are the canonical Guests team, which is created in every org and is scoped to specific repositories rather than all of them.
Add a guest
- Go to Org admin → Members → Invite member → enter the email → in Team(s), select Guests (and nothing else).
- Choose which repositories the Guests team can read:
frem.sh/org/<org>/teams/guests→ Repositories → add the repositories you want. - Send the invitation. When they accept they can read exactly those repositories.
To move an existing free Reader down to specific repositories, open their Manage drawer and move them from Viewers to Guests. They stay free either way.
Guests and Collaborators are managed by fremforge and cannot be deleted. They set what you pay — Guests keeps repository-scoped readers free, Collaborators is what makes a repository-scoped writer a paid seat. Removing either would silently re-price your org, so both are locked, like Members and Viewers. You can freely change which repositories each one covers, and who is in it.
When seats are full
If your org has reached its seat cap, a member who tries to access the org is shown a “seats full” page at /<org>/seats-full instead of the resource they requested. From that page they can send a one-click request to the org’s owners to add a seat.
Owners receive that request (by email and in the admin notifications bell) and can add a seat from Org admin → Billing, which clears the block for the waiting member. Raise the seat cap before the member can proceed; until then their access stays paused at the seats-full page.
Changing roles
A member’s role (Owner, Member, or Reader) is changed in-product from the Manage drawer on the Members page. Under the hood the role maps to Forgejo team membership: Owners = full org admin, Members = scoped read/write access defined by the team’s repo grants, Viewers = read-only (and free). Moving a member into Viewers-only drops them from the billable seat count at the next billing cycle.
- Go to Org admin → Members (
/<org>/_admin/members). - Open the Manage drawer for the member.
- Pick the new role and confirm. The matching Forgejo team change is applied immediately.
For finer team composition (custom teams, repo-scoped grants) use the Forgejo-native team page at frem.sh/org/<org>/teams. Role changes take effect immediately. There is no grace period or confirmation email sent to the member.
Removing a member
- Go to Org admin → Members (
/<org>/_admin/members). - Open the Manage drawer for the member and choose Remove member.
- Confirm the removal.
What happens immediately:
- Access to all org repositories is revoked.
- Any active sessions (browser or API) for that user are invalidated.
- The member is removed from any team assignments within the org.
What does not change:
- Repositories are not deleted. Repos belong to the org, not to individual members. A member who owned repos in the org does not take those repos when they leave.
- Issues, PRs, and commits remain attributed to their username. Historical contribution records are preserved.
- Open PRs and issues they authored remain open and unmodified.
The removed member is taken out of the billable seat count at the next billing cycle. There is no credit for the current period.
Offboarding checklist
When a member leaves the org, run through this checklist before completing the removal.
- Transfer repository ownership if the departing member owns any repos directly (check Org admin → Repositories for repos with their username as owner). Transfer to the org or to another member before removing them.
- Rotate secrets they may have known. Check which secrets were created or last updated while they had access. Rotate any that are now exposed by their departure.
- Revoke API tokens they created. Go to Org admin → API tokens (
/<org>/_admin/api-tokens) to see all org API tokens. Revoke any token created by the departing member. - Check for personal access tokens (PATs). PATs are tied to the user’s account, not the org. Once removed from the org, their PATs can no longer access org resources. But if the departing member was an Owner, confirm no tokens with elevated scopes were shared with external systems under their name.
- Review active integrations and webhooks. If any webhook or external integration is authenticating as this user, update it to use an org API token or another account.
SCIM-managed deprovisioning
If SCIM provisioning is configured for the org, user lifecycle is managed by the connected IdP (Okta, Entra ID, etc.). Deactivating or removing a user in the IdP deactivates them in fremforge automatically within the SCIM sync interval, which is typically under five minutes.
When a user is deactivated via SCIM:
- Their fremforge session is invalidated immediately.
- They cannot sign in via SSO or local password.
- Their seat is removed from the billable count at the next billing cycle.
Manual removal via Org admin → Members is not required when SCIM is active. The IdP is the source of truth for membership. Removing a user in fremforge without deactivating them in the IdP will cause SCIM to re-provision them on the next sync.
See SCIM provisioning for setup instructions.
SSO-only members
A member who has only ever signed in via SSO has no local fremforge password. Their identity is entirely controlled by the IdP.
To block a SSO-only member’s access:
- Revoke their access in the IdP (deactivate the account, remove from the app assignment, or disable SSO for their account).
- Optionally remove them from the org in fremforge to clean up the seat count.
Revoking IdP access alone is sufficient to prevent sign-in. The fremforge session will fail at the next SSO validation check. If SCIM is enabled, the IdP deactivation also triggers automatic deprovisioning without the manual org removal step.
Re-inviting a former member
To re-invite someone who was previously removed, send them a fresh invitation from Org admin → Members → Invite member as normal.
When they rejoin:
- Previous commits, issues, and PRs remain attributed to their username.
- Repository access is determined freshly by org role and any repo-level collaborator assignments. No previous access configuration is automatically restored.
If the former member deleted their fremforge account after leaving, their username may show as a deleted-account indicator on historical contributions. If a different person has taken that username in the interim, historical attribution reflects the original account via the underlying user ID, not just the username string.
Per-repository permissions
Org-level roles determine baseline access. For finer-grained control, you can add individual users as collaborators on specific repositories.
Add a collaborator:
- Go to Repository → Settings → Collaborators.
- Search for the user by username or email.
- Select a permission level:
| Permission | What they can do |
|---|---|
| Read | Clone, pull, view issues and PRs |
| Write | Read access plus push branches, create and close issues and PRs |
| Admin | Write access plus manage repository settings, branch protection, webhooks, and secrets |
Collaborator permissions are additive on top of the user’s org role, not a replacement — the higher of the two applies. A Reader with Write collaborator access on a repo can push to that repo. An Owner collaborator gains nothing beyond what the Owner role already grants.
Collaborators must be members of your org
A collaborator has to be a member of the organisation that owns the repository. You cannot attach someone from another organisation, and you cannot add an outside account directly to a repository — invite them to the org first (as a Guest if they only need read), then grant repository access.
This is a change from earlier behaviour, where a repository admin could attach any existing account on the instance. Requiring membership means everyone with access to your code appears in Org admin → Members, which is also what makes access reviews and offboarding complete.
What a collaborator costs
Only write costs a seat:
| Collaborator permission | Seat |
|---|---|
| Read | Free — same as a Guest, scoped to that repository |
| Write or Admin | Consumes a billable seat |
Granting write to someone who is currently free (a Reader or Guest) automatically adds them to the canonical Collaborators team, which is what makes them a paid seat. You do not have to move them by hand. Someone who is already billable — a Member, an Owner, or an existing Collaborator — is not charged twice.
If that seat would take you past your seat cap:
- With seat overage enabled, the grant succeeds and the extra seat appears on your next invoice.
- With seat overage disabled, the grant is refused and you are pointed at Org admin → Billing → Seats. Turning seat overage off at Org admin → Billing is how you stop fremforge adding paid seats automatically — the same switch that governs invitations and SSO-provisioned members.
Removing someone’s seat does not remove their access outright. Write grants that are no longer covered by a seat are reduced to read after a 7-day grace period, so losing a seat turns a Collaborator into the equivalent of a Guest rather than locking them out. Restore the seat within that window and nothing changes.
Via REST API
The day-to-day member-lifecycle flow (invite / list / revoke / remove) is available on the public API surface. Use this when scripting onboarding from an HRIS, automating offboarding, or driving operations from an AI agent.
- List invitations
GET /api/v1/orgs/:slug/members/invitations?status=pending(scopeseats:read) - Invite a member
POST /api/v1/orgs/:slug/members/invitationsbody:{ "email": "...", "full_name": "...", "team_names": [...] }(scopeseats:write) - Revoke a pending invitation
DELETE /api/v1/orgs/:slug/members/invitations/:id(scopeseats:write) - Remove a member
DELETE /api/v1/orgs/:slug/members/:login(scopeseats:write) - Grant / dismiss a seat hold
POST /api/v1/orgs/:slug/members/seat-holds/:id/grantor.../dismiss(scopeseats:write)
Requires a Personal Access Token (PAT) with the seats:write scope:
curl -X POST \
-H "Authorization: Bearer ${FREMFORGE_PAT}" \
-H "Content-Type: application/json" \
-d '{"email":"new.hire@example.com","full_name":"New Hire","team_names":["engineering"]}' \
https://frem.sh/_app/api/v1/orgs/acme/members/invitationsSee the public REST API reference for the full OpenAPI specification.
Cross-references
- SCIM provisioning, automated user lifecycle via Okta, Entra ID, or any SCIM 2.0-compliant IdP
- OIDC SSO, configure SSO so members sign in with their corporate identity
- Billing, how seats are counted and when removed members leave the billable count
- Org admin, full reference for the org admin surface
- API, manage members programmatically via the REST API