Githome
Accounts: Invitations
Docs / Accounts

Invitations

How people join an invite-only Githome instance, who can invite, Add people by username or email, accepting or declining invitations, revoking them, the CLI and API, and access requests.

Githome is invite-only: nobody can sign up from the sign-in page, and open sign-up is off on git.pkgforge.dev. Anyone can still browse and clone public repositories without an account; a write needs an account. Of the invitations, only an instance invite makes an account, and only the superadmin makes one, on the page People of the dash. A person joins by opening its link, picking a username and creating a passkey. Organizations and repositories have an Add people form that takes a username or the email address of an account. Either way the person gets an invitation, as on GitHub, and accepts it under Settings → Invitations. Githome sends no email for any invitation: the person who invites sends the link.

Without an invitation, ask the superadmin for an invitation link. A request that reaches the page Early access of the dash is read there, and the superadmin decides whether to invite the person.

How sign-up works

  1. The superadmin makes an instance invite for an email address on the page People of the dash. Invite on a request of the page Early access makes one too. Only an instance invite makes an account. An invite to an organization or a repository goes to an address that has an account. One to an address with no account answers 422 ("ask the administrator to invite this address").
  2. The dash shows the link of an instance invite once, and the superadmin sends it. Githome sends no email for any invite. For an organization or a repository, the page shows the link to the person who invites, who sends it. The invited person also gets an in-app notification and sees the invite under Settings → Invitations.
  3. The invited person opens the whole link of the instance invite, https://git.pkgforge.dev/invite/<token>#proof=<proof>. They pick a username, create a passkey and are signed in. The link is the proof of the invite, so whoever holds it creates the account, with the address of the invite. Nothing proves the inbox. The token alone (https://git.pkgforge.dev/invite/<token>) shows This link is incomplete and asks for the whole link.
  4. Their account is active, and every open invite for their email address is accepted at once: they join each organization and repository they were invited to.
  5. They land on the dashboard.

Nobody needs a password or a Cloudflare account. After joining, they use their passkey in the browser and create personal access tokens for Git, the CLI and agents.

Who can invite

WhoWhat they can invite toWhere
The superadmin, in the dashThe instance (no organization or repository)The page People of the dash
Organization ownersTheir organization, as member, admin or ownerThe organization's People tab (Add people), githome invite --org, the API
Organization adminsTheir organization, as member or adminThe organization's People tab (Add people), githome invite --org, the API
Repository admins (including the owner of a personal repository)One repository, with a repository role from read to adminThe repository's Settings → Collaborators page (Add people), PUT /api/v3/repos/{owner}/{repo}/collaborators/{username}

Everyone else, including organization members and people with a lower repository role, can't create invites.

Invite from the web UI

Invite someone to the instance

The superadmin only, in the dash. An instance invite lets the person create an account, without adding them to any organization or repository. An instance invite of an address whose account waits (pending) makes that account active.

  1. On the page People of the dash, enter the Email address under Invite a person, and click Make an invitation link.

The dash shows the link once: "The link for <email> works once, until <time>. Copy it and send it." Githome sends no email for it. It expires in 14 days and works once: they pick a username and create a passkey.

An address can have only one pending instance invitation at a time (letter case doesn't matter). A second one is refused with "friend@example.com already has a pending invitation; revoke it first to send a new one"; revoke the first one under Site invitations that wait on the same page, then invite the address again.

Add people to an organization

Organization owners and admins. The Add people form on the organization's People tab takes a username or an email address.

  1. Open the organization's page, for example https://git.pkgforge.dev/acme, and click the People tab.
  2. Under Add people, enter a Username or email: diffy (or @diffy), or the email address of their account, such as friend@example.com.
  3. Choose a Role: Member (default), Admin or Owner. Only owners can choose Owner.
  4. Click Add.
You enteredWhat happens
A usernameGithome sends them an invitation: "Invited diffy to acme as member. They join once they accept." They get an in-app notification, and join when they accept it under Settings → Invitations (see Invitations you receive). If they already have a pending invitation to the organization, it offers the role you chose instead of sending another: "diffy already had a pending invitation; it now offers the admin role."
An email addressGithome creates an invitation for the account of that address, and sends no email. Nobody joins without agreeing. The page shows Invitation sent to friend@example.com with the link and a copy button. Its note reads "Send them this link yourself: Githome sends no email for invitations. It works once and expires in 14 days, and they join when they accept it, signed in to their account." The person also gets an in-app notification. An address with no account answers "friend@example.com has no account of Githome: ask the administrator to invite this address".

The invitation then appears under Pending invitations on the same tab, with who sent it, when, the expiry date and the role. An invitation sent to a username shows as @diffy, never the person's email address. See Organizations for every message the form can show.

An email address can have only one pending invitation per organization, whether it came from this form, the CLI or the API. Letter case doesn't matter: Friend@Example.com and friend@example.com are the same address. To send a new one, revoke the old one first ("friend@example.com already has a pending invitation; revoke it first to send a new one").

Revoke an invitation

Every pending invitation can be revoked until it's used:

  • organization invitations on the organization's People tab (owners and admins);
  • repository invitations on the repository's Settings → Collaborators page (repository admins);
  • instance invitations on the page People of the dash (the superadmin).

Under Pending invitations, click Revoke next to the invitation and confirm "Revoke the invitation for friend@example.com? The link stops working." (for an invitation sent to a username: "Revoke the invitation for @diffy?"). You see "Invitation revoked." Opening the link afterwards shows "this invite is invalid, already used, or expired", and an invitation sent to a username disappears from the person's Settings → Invitations. The person isn't notified, and you can invite the same address or username again.

Add people to a repository

Repository admins. The Add people form on the repository's Settings → Collaborators page (/acme/website/settings/access) works the same way, and also accepts agents:

  1. Under Add people, enter a Username or email: a person (diffy), an agent (review-bot) or the email address of an account (friend@example.com).
  2. Choose a Role: Read, Triage, Write (default), Maintain or Admin.
  3. Click Add.
You enteredWhat happens
The username of a personGithome sends them an invitation: "Invited diffy with write access. They get access once they accept." They get an in-app notification, and get the role when they accept it under Settings → Invitations (see Invitations you receive). If they already have a pending invitation to the repository, it offers the role you chose instead of sending another: "diffy already had a pending invitation; it now offers admin access."
The username of an agent, of a person who already is a direct collaborator, of a member of the organization that owns the repository, or your ownThey get the role right away as a direct collaborator, with no invitation: "diffy now has write access. We let them know." People get an in-app notification. A collaborator's role changes to the one you chose.
An email addressGithome creates an invitation for the account of that address, and sends no email. The page shows Invitation sent to friend@example.com with the link to send yourself. The person also gets an in-app notification. When they accept it, they get that role on the repository.
MessageCause
"no one has the username diffy; to invite a person by email, enter the address of their account"No account has that username.
"friend@example.com has no account of Githome: ask the administrator to invite this address"No account has that address. The superadmin makes an instance invite of it first, on the page People of the dash.
"acme is an organization; add its people instead"Organizations can't be collaborators.
"diffy's account is disabled"The superadmin disabled the account.
"enter a valid email address"The text has an @ but isn't a complete address.
"friend@example.com already has a pending invitation; revoke it first to send a new one"The address already has an open invitation to this repository (letter case doesn't matter). Revoke it under Pending invitations, then add the address again.

Pending invitations are listed under Pending invitations on the same page, where you can revoke them. See Permissions for what each role allows.

Invite from the CLI

githome invite invites to an organization. Without --org it answers 403, because the instance invitation is in the dash. You need to be logged in (githome login) with a token that has the admin scope and isn't restricted to repositories; a read or write token gets 403 this token needs the admin scope. If you don't have the CLI yet:

curl -fsSL https://git.pkgforge.dev/install | bash
githome login --scope admin

The CLI needs Node.js 26 or later, and the installer puts a private copy of Node.js 26 on a machine that has none.

# Invite to the acme organization as a member (the default role)
githome invite friend@example.com --org acme

# Invite as an organization admin
githome invite friend@example.com --org acme --role admin
OptionDescription
-o, --org ORGOrganization to join. Without it, the core answers 403: the instance invitation is in the dash.
-r, --role ROLEmember (default), admin or owner. Needs --org.
--jsonPrint the API response (id and url) as JSON.

The command prints the invite link and asks you to send it, because Githome sends no email for it. The link is valid for 14 days. The address must belong to an account of Githome, or the command fails with 422 (see API errors). The person accepts the invitation signed in to that account (see Accept an invite with an existing account). It refuses an address that already has a pending invitation to the organization (see API errors). The CLI can't create repository invites; use the repository's Settings → Collaborators page or PUT /api/v3/repos/{owner}/{repo}/collaborators/{username}. See CLI reference for every command.

Invite with the API

The organization endpoint takes a JSON body and returns 201 Created with the invite's id and url. Githome sends no email, so send the link yourself.

Inviting to an organization is an account-level action. The endpoint needs a personal access token with the admin scope that isn't restricted to repositories, or a browser session. A token with only read or write gets 403 this token needs the admin scope, and a token restricted to repositories gets 403 this token is limited to repositories and can't change account settings. See Personal access tokens.

Organization invite

POST /api/v3/orgs/{org}/invitations

FieldTypeDescription
emailstringRequired. The email address of the account to invite.
rolestringmember (default), admin or owner.
curl -X POST https://git.pkgforge.dev/api/v3/orgs/acme/invitations \
  -H "Authorization: Bearer ghome_..." \
  -H "Content-Type: application/json" \
  -d '{"email": "friend@example.com", "role": "member"}'
{ "id": "3f1c0e8a9b7d4c2e8f6a5b4c3d2e1f0a", "url": "https://git.pkgforge.dev/invite/..." }

The caller must be an owner or admin of the organization. Only owners can invite with the owner role. Like the CLI and the web form, this endpoint creates an invitation, and adds no account directly. The address must belong to an account of Githome: an address with no account answers 422. It refuses an address that already has a pending invitation to the organization (compared without regard to letter case). An address whose account is already a member gets an invitation too, so the answer doesn't tell you who is a member. Accepting it changes nothing.

Instance invite

POST /api/v3/invitations answers 403 to each caller: the instance invitation is on the page People of the dash.

Repository invite by username

PUT /api/v3/repos/{owner}/{repo}/collaborators/{username} with {"permission": "write"} works like Add people on the repository's Settings → Collaborators page. It needs admin on the repository, through an admin token (it may be restricted to that repository) or a browser session.

  • When the person gets an invitation, the answer is 201 Created with the invitation: id, repository (full_name, name, owner.login), invitee, inviter (login), permissions, created_at, expires_at and html_url (their Settings → Invitations page). If they already had a pending invitation to the repository, the same invitation now offers the new role.
  • When the role applies at once (an agent, someone who already is a direct collaborator, a member of the organization that owns the repository, or yourself), the answer is 204 No Content.
curl -X PUT https://git.pkgforge.dev/api/v3/repos/acme/website/collaborators/diffy \
  -H "Authorization: Bearer ghome_..." \
  -H "Content-Type: application/json" \
  -d '{"permission": "write"}'

It answers 404 user not found when no account has that username, 422 diffy's account is disabled for a disabled account, and 429 you can send at most 50 invitations in 24 hours; try again later like the other ways of inviting.

List and revoke pending invitations

Method and pathWho
GET /api/v3/orgs/{org}/invitations, DELETE /api/v3/orgs/{org}/invitations/{id}The organization's owners and admins
GET /api/v3/repos/{owner}/{repo}/invitations, DELETE /api/v3/repos/{owner}/{repo}/invitations/{id}The repository's admins
GET /api/v3/invitations, DELETE /api/v3/invitations/{id}Nobody: each answers 403, and the page People of the dash lists and revokes the instance invitations

Each listed invitation has an id, email, login, role, inviter, created_at and expires_at. An invitation sent to an email address has the email and a login of null; one sent to a username has the login and an email of null. DELETE returns 204 No Content, or 404 no pending invitation with this id when the invitation was already used or revoked, or belongs to another organization, repository or kind. Revoking an organization invitation needs an admin token, and revoking a repository invitation needs admin on the repository. Agents use the MCP tools list_invitations and revoke_invitation with owner and repo, or org. Their instance branch answers that the administration is in the dash.

API errors

StatusMessageCause
401sign in requiredNo token was sent.
403this token needs the admin scopeThe token's scope is read or write. Create an admin token.
403this token is limited to repositories and can't change account settingsThe token was created with a repository list. Use a token without one.
403only organization owners and admins can inviteYou are not an owner or admin of the organization.
403only owners can invite ownersAn organization admin asked for "role": "owner".
403the administration of the site is in the dash of this deploymentPOST /api/v3/invitations: the instance invitation is on the page People of the dash.
429you can send at most 50 invitations in 24 hours; try again laterYou sent 50 invitations in the last 24 hours. See Limits.
404not foundThe organization doesn't exist, or the name is not an organization.
422a valid email is requiredThe email field is missing or isn't an email address.
422role must be member, admin or ownerrole has another value.
422friend@example.com has no account of Githome: ask the administrator to invite this addressNo account has that address. The superadmin makes an instance invite of it first, on the page People of the dash.
422friend@example.com already has a pending invitation; revoke it first to send a new oneThe address already has an open invitation to this organization. Letter case doesn't matter. Revoke the organization invitation on the People tab first.

Error bodies are JSON: {"message": "...", "documentation_url": "..."}.

The full endpoint list is in the API reference.

No invite email

Githome sends no email for any invitation: of the instance, an organization or a repository, by email address or by username. The person who invites sends the link.

InviteWhat reaches the invited person
Organization or repositoryThe link from the person who invites, and an in-app notification that opens Settings → Invitations (/settings/invitations)
InstanceThe link of the dash, from the superadmin

On Settings → Invitations you accept or decline an invitation of an organization or a repository. See Invitations you receive.

RuleValue
Lifetime14 days from creation
UsesOnce. A used, revoked or expired link shows "this invite is invalid, already used, or expired" (HTTP 404). If you are already signed in, the page still shows Accept invite, and clicking it answers "this invite is invalid or has expired" (HTTP 404).
Who can use itAn organization or repository invite: only the account with the email address it was sent to. An instance invite: whoever holds the whole link, and the account takes the address of the invite.
Link formatThe link of an instance invite is https://<host>/invite/<token>#proof=<proof>. The proof is in the URL fragment, which browsers never send to the server. So a request log holds the token alone, which makes no account. The page removes the proof from the address bar. A proof in the query (?proof=) works too. The link of an organization or repository invite is https://<host>/invite/<token>, with no proof: its person signs in to accept it.
What joining acceptsEvery open invite for that email address, not just the one you opened
WithdrawingPending invitations can be revoked: organization invitations on the organization's People tab, repository invitations on the repository's Settings → Collaborators page, instance invitations on the page People of the dash. Otherwise they stop working once used or after 14 days.

The token of an instance invite without its proof shows This link is incomplete: open the whole link that the person who invited you sent. An organization or repository invite makes no account. If its address has no account, its page answers 403 with Ask for an invitation, and the passkey sign-up makes no account. Ask the superadmin to invite the address first.

An invite to the wrong address can be revoked until it is used. If an instance invite made an account for the wrong person, the superadmin disables it on the page People of the dash (see Site administration).

Choosing a username

The Join Githome page suggests a username made from the part of the email address before the @. Rules:

  • Starts with a letter or digit, then letters, digits, - and _, up to 39 characters.
  • Not already taken (case-insensitive) and not reserved. Reserved names include api, mcp, settings, new, notifications, invite, login, admin, explore, docs, auth, signin, signup, security, status, githome, ghost, github-actions, noreply, support, abuse, postmaster, root and staff.

Your username is part of your repository URLs (https://git.pkgforge.dev/<username>/<repo>). You can change it later under Settings → Profile, which changes those URLs; existing clones then need a new remote URL (see Profile and preferences).

MessageWhat to do
"Usernames use letters, numbers and dashes (up to 39), and some names are reserved."Pick a name that follows the rules above.
"The username <name> is taken. Pick another one."Pick another name.
"<email> already has an account. Sign in with its passkey, then open this invite again."The address already has an account: sign in, then open the link and click Accept invite.
"This invite has no email address. Sign in first, then open it again."Sign in with your existing account, then open the link again.

Accept an invite with an existing account

If the invited address already has an account:

  1. Open the invite link that the person who invited you sent. The page says the address already has an account and shows a Sign in button. (The token of an instance invite without its proof shows This link is incomplete, which also offers Sign in to accept.)
  2. Sign in with your passkey. Githome brings you back to the invite.
  3. Click Accept invite.

You are taken to the repository or organization you were invited to. The invite only works when the signed-in account's email address matches; otherwise you get "this invite was sent to <email>; sign in with that address" (HTTP 403).

When someone accepts your invite, you get an "@<username> accepted your invitation" notification, and an email where the deployment sends email (part of the Organizations email group, which you can turn off; see Notifications). For an invitation you sent to a username, it doesn't show the person's email address.

Invitations you receive

An organization owner or admin, or a repository admin, can add you by username or by the email address of your account. You then get an invitation, not access, as on GitHub. You get an in-app notification (kind invitation, for example "diffy invited you to acme as member" or "diffy invited you to acme/website as write"). It leads to Settings → Invitations, and Githome sends no email for it. You have no access until you accept.

Accept or decline in the web UI

Open Settings → Invitations (/settings/invitations). It lists your pending invitations to organizations and repositories: those sent to your username, and those sent to your email address. Each one shows the organization or repository, the role, who invited you, when, and when it expires. With none, the page shows "No pending invitations."

  • Accept gives you the role and takes you to the repository or organization.
  • Decline deletes the invitation. You see "Invitation declined." Nobody is told, and they can invite you again.

An invitation expires after 14 days. If the admin adds you again while one is pending, that invitation offers the new role; you don't get a second one.

If your account is waiting for an invite (see Pending accounts), your invitations appear under Your invitations on the Waiting for an invite page, with the same Accept and Decline buttons. Accepting an invitation of an organization or a repository doesn't make your account active. The superadmin does that on the page People of the dash.

Accept or decline with the API

The endpoints follow GitHub's. Listing needs a token with at least the read scope; accepting and declining need write or admin. All of them refuse tokens restricted to repositories (403 this token is limited to repositories and can't change account settings).

Method and pathWhat it does
GET /api/v3/user/repository_invitationsYour pending repository invitations: id, repository (full_name, name, owner.login), invitee, inviter (login), permissions, created_at, expires_at, html_url
PATCH /api/v3/user/repository_invitations/{id}Accept a repository invitation. Returns 204 No Content.
DELETE /api/v3/user/repository_invitations/{id}Decline a repository invitation. Returns 204 No Content.
GET /api/v3/user/memberships/orgsYour organization memberships, pending invitations first. Add ?state=active or ?state=pending for only one kind.
GET /api/v3/user/memberships/orgs/{org}Your membership of one organization, active or pending. 404 not found when you have neither.
PATCH /api/v3/user/memberships/orgs/{org}With {"state": "active"}, accept your pending invitation to the organization. Returns the membership.

A membership has url, state (active or pending), role (admin or member, as on GitHub, where owners count as admin), githome_role (owner, admin or member), organization (login, url) and user.

# List your repository invitations
curl https://git.pkgforge.dev/api/v3/user/repository_invitations -H "Authorization: Bearer ghome_..."

# Accept one
curl -X PATCH https://git.pkgforge.dev/api/v3/user/repository_invitations/3f1c0e8a9b7d4c2e8f6a5b4c3d2e1f0a -H "Authorization: Bearer ghome_..."

# Accept an invitation to the acme organization
curl -X PATCH https://git.pkgforge.dev/api/v3/user/memberships/orgs/acme \
  -H "Authorization: Bearer ghome_..." \
  -H "Content-Type: application/json" \
  -d '{"state": "active"}'
StatusMessageCause
404no pending invitation with this idThe id is unknown, the invitation was already accepted, declined, revoked or expired, or it is someone else's.
404no pending invitation to this organizationPATCH /user/memberships/orgs/{org} when you have no pending invitation to it and aren't a member. If you already are a member, the answer is your active membership.
422state must be "active"The PATCH body has another state, or none.

An account that is waiting for an invite can't use the API; it accepts on the Waiting for an invite page.

Pending accounts

An account can exist without being active. On git.pkgforge.dev none is pending: its accounts are made from an instance invite of the dash, and it has no Cloudflare Access sign-in and no open sign-up, the ways in which a pending account arises. Where one exists, a pending account:

  • can sign in, but only sees a Waiting for an invite page, which lists its pending invitations to organizations and repositories under Your invitations,
  • can't see repositories, create organizations or tokens, or use the API (requests return "your account is waiting for an invite"),
  • becomes active when the superadmin makes an instance invite for its email address, or the superadmin clicks Approve on its access request on the page People of the dash. An invitation of an organization or a repository doesn't make it active, whether it is made or accepted.

Access requests

This applies only where a pending account exists, which it doesn't on git.pkgforge.dev. From the Waiting for an invite page, a person with a pending account can ask the superadmin for access:

  1. Optionally write a Note to the administrators (up to 500 characters), for example who you are and what you want to work on.
  2. Click Request access. You see "Request sent. An administrator will review it."

The request appears under Access requests on the page People of the dash. There the superadmin clicks Approve (the account becomes active) or Deny (the account is disabled). Sending another request replaces the earlier note.

Approving an account doesn't add it to any organization or repository; invite the person or add them by username for that.

How invitations differ from GitHub

  • On GitHub anyone can create an account. On githome, which is invite-only, the way in on git.pkgforge.dev is an instance invite of the dash. Anyone can browse and clone public repositories without an account.
  • GitHub organization and repository invitations go to existing GitHub users. Githome invites of an organization or a repository go to existing accounts too, by username or by the email address of the account.
  • Add people takes a username or an email address, as on GitHub. Someone added by username gets an invitation to accept under Settings → Invitations, as on GitHub. The email address of an account gets an invitation link, and an address with no account answers 422.
  • GitHub emails each invitation. Githome sends no email for any invitation: the person who invites sends the link, and the invited person gets an in-app notification.
  • Pending invitations of every kind can be revoked, in the web UI, the API or over MCP; otherwise they expire after 14 days.