# Githome > Githome is a private, GitHub-compatible Git forge at git.pkgforge.dev: repositories, pull requests, issues and an MCP server for AI agents, on Cloudflare. Accounts are by invitation. This file holds git.pkgforge.dev as Markdown: the home page, the product and company pages, then every page of the Githome docs (https://git.pkgforge.dev/docs) in reading order. Each page starts with a level-1 heading and its source URL. The REST API is also available as OpenAPI 3.1 at https://git.pkgforge.dev/docs/api/openapi.json. --- # Githome > Githome at git.pkgforge.dev: a private, GitHub-compatible forge on Cloudflare, with gh, an MCP server for AI agents and push mirrors. Accounts by invitation. Source: https://git.pkgforge.dev/ (last updated 2026-11-12) ## A private, GitHub-compatible forge for people and AI agents Githome is the internal forge at git.pkgforge.dev: Git repositories, pull requests, issues and releases behind GitHub-compatible REST and GraphQL APIs, an MCP server, the githome CLI and gh for agents, and push mirrors that copy each repository with its forge state. It runs on Cloudflare. Accounts are by invitation, and public repositories are open to read. - **Invite only**: The superadmin invites each account. Anyone can browse and clone public repositories. - **gh**: works as it does with GitHub Enterprise, through the GitHub-compatible REST and GraphQL APIs. - **/mcp**: The MCP server for Claude, Claude Code, Codex and any MCP client, with a browser sign-in or a token. - **1 person**: approves an agent's pull request before it merges, enforced by the server, unless a repository waives it. ## What you get - **[Git hosting](https://git.pkgforge.dev/docs/repositories/git)**: Clone, fetch and push over HTTPS with Git LFS. Every repository is its own strongly consistent store, and pushes that leak a credential are refused. - **[Pull requests with intent](https://git.pkgforge.dev/docs/collaboration/pull-requests)**: Reviews, required approvals and checks, auto-merge and a merge queue. Each pull request says what it's meant to do, so reviewers check the right thing. - **[GitHub-compatible APIs](https://git.pkgforge.dev/docs/reference/rest-api)**: REST and GraphQL APIs that follow GitHub's, so gh, Git and GitHub API clients work with git.pkgforge.dev as they do with GitHub Enterprise. - **[Push mirrors](https://git.pkgforge.dev/docs/self-hosting/deploy#mirrors-and-backups)**: Each repository is pushed with its forge state (refs/githome/meta) to GitHub, Cloudflare Artifacts, GitLab, Forgejo or Codeberg, and backups go to a bucket off Cloudflare once its credentials are set. - **[AI agents with guardrails](https://git.pkgforge.dev/agents)**: Agents get their own accounts and tokens and work through the MCP server, the githome CLI and gh. They can't push to protected branches, and a person approves their pull requests. - **[Secure by default](https://git.pkgforge.dev/security)**: Passkeys instead of passwords, accounts by invitation, encrypted secrets, scoped tokens and an append-only audit log. ## Built for AI coding agents Claude Code, Codex and other agents work through Git, the GitHub CLI, the REST API or the built-in MCP server, as accounts of their own, and the server keeps a person in charge of what lands. Githome includes no model access. Agent tasks, agent review, sandboxes and browser terminals need the forge CI, which is dormant on git.pkgforge.dev. - **[Agent accounts with guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails)**: Each agent has its own login and tokens, owned by a person or an organization. It can't push to protected branches or manage secrets, and a person approves its pull requests. - **[An MCP server](https://git.pkgforge.dev/docs/agents/mcp)**: Claude, Claude Code, Codex and any MCP client read and change code, pull requests, issues and releases, and search the docs, at /mcp. - **[Cloud agents](https://git.pkgforge.dev/docs/connect/cloud-agents)**: A repository's Agent setup gives a cloud agent, such as a Claude Code cloud environment or Codex in the cloud, a token limited to that repository and a setup script. - **[Today and Needs you](https://git.pkgforge.dev/docs/agents/today)**: One page each morning: what needs you, what your agents are working on, and what changed since yesterday, across every repository. - **[Merge on green](https://git.pkgforge.dev/docs/collaboration/merge-on-green)**: Pull requests merge by themselves once their checks pass, with or without a person's approval, as you choose. An agent's change to a workflow file still needs a person to merge it. - **[Docs written for agents](https://git.pkgforge.dev/docs/agents/docs-for-agents)**: Every docs page is also Markdown, with llms.txt and llms-full.txt, and the MCP server searches and reads the docs. ## Works where you and your agents already work - **[Claude Code](https://git.pkgforge.dev/docs/connect/claude-code)**: Add the MCP server once for every project, then run /mcp in Claude Code to sign in through the browser. `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp` - **[Codex](https://git.pkgforge.dev/docs/connect/codex)**: The same MCP server for OpenAI's Codex CLI, with a browser sign-in, or a token with --bearer-token-env-var GITHOME_TOKEN. `codex mcp add githome --url https://git.pkgforge.dev/mcp` - **[Claude and other MCP clients](https://git.pkgforge.dev/docs/connect/claude)**: Add the server URL to Claude as a connector, or to Cursor or any other MCP client, and sign in through the browser. `https://git.pkgforge.dev/mcp` - **[The githome CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in)**: Signs in through the browser and sets up git and gh in one command. It needs Node.js 26 or later, and the script installs a private copy when the machine has no Node.js 26. `curl -fsSL https://git.pkgforge.dev/install | bash` - **[gh, the GitHub CLI](https://git.pkgforge.dev/docs/agents/github-cli)**: Pull requests, issues, releases and gh api work as they do with GitHub Enterprise, so agents use the commands they know. `githome auth setup-gh` - **[Git and your editor](https://git.pkgforge.dev/docs/repositories/git)**: Any editor clones, pulls and pushes with the plain HTTPS URL of a repository. `git clone https://git.pkgforge.dev/OWNER/REPO.git` ## gh and Git, as you use them with GitHub Githome's REST and GraphQL APIs follow GitHub's, so gh talks to git.pkgforge.dev the way it talks to a GitHub Enterprise Server, and Git works over HTTPS with Git LFS. `githome setup` signs in through the browser and sets up git and gh. ```sh curl -fsSL https://git.pkgforge.dev/install | bash githome setup # sign in, set up git and gh git clone https://git.pkgforge.dev/OWNER/REPO.git cd REPO gh pr create --title "Fix the parser" --draft gh pr merge --auto --squash ``` The forge CI of git.pkgforge.dev is dormant: an event starts no workflow run, and a dispatch is refused with "CI is off on this deployment". External CI and bots report check runs and commit statuses through the API, and branch protection can require them. ## Accounts by invitation, public read Anyone can browse and clone public repositories without an account. A write needs an account: the superadmin creates or invites each one and sends the one-time invitation link by hand. Open sign-up is off, and people sign in with a passkey. Bugs and questions go to the public tracker [Azathothas/issues](https://github.com/Azathothas/issues) with the label `git.pkgforge.dev`. ## Frequently asked questions ### What is Githome? Githome is the private, internal forge at git.pkgforge.dev. It hosts Git repositories, pull requests, issues and releases behind REST and GraphQL APIs that follow GitHub's, so Git, gh and AI agents work with it as they do with GitHub. It runs on Cloudflare. It is not a product for sale: there is no price, no plan and no hosted service to sign up for. ### Who can use git.pkgforge.dev? Anyone can browse and clone its public repositories without an account. A write needs an account, and accounts are by invitation: the superadmin invites each one and sends the one-time invitation link by hand. Open sign-up is off. People sign in with a passkey, and someone who lost their passkeys asks the superadmin for a sign-in link. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). ### Does Githome work like GitHub? For Git, pull requests, issues and releases, yes: Git works over HTTPS with Git LFS, and gh talks to git.pkgforge.dev the way it talks to a GitHub Enterprise Server. Branch protection, required reviews and checks apply to gh as they do on the web. See [GitHub CLI and Claude Code](https://git.pkgforge.dev/docs/agents/github-cli) and the [REST API](https://git.pkgforge.dev/docs/reference/rest-api). ### Do GitHub Actions workflows run on git.pkgforge.dev? No. The Actions code is in Githome and reads `.github/workflows` with GitHub's syntax, but the forge CI of git.pkgforge.dev is dormant: an event starts no run, and a dispatch is refused with "CI is off on this deployment". External CI and bots still report check runs and commit statuses through the API, and branch protection can require them. See [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). ### Is Githome built on Cloudflare? Yes. One Cloudflare Worker serves the site, the API, Git and the MCP server; each repository is its own Durable Object, with large objects in R2 and accounts in D1; Queues and Workflows drive webhooks, email and background work. No Cloudflare Container runs, because the forge CI is dormant. See [Built on Cloudflare](https://git.pkgforge.dev/built-on-cloudflare). ### How does Githome work with Claude Code, Codex and other AI agents? Agents connect to the MCP server at `https://git.pkgforge.dev/mcp` with a browser sign-in or a token, or use Git, gh and the REST API with an agent token. Claude Code: `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`. Codex: `codex mcp add githome --url https://git.pkgforge.dev/mcp`. Each agent is an account of its own: it can't push to protected branches, and its pull requests need a person's approval. See [Githome for AI agents](https://git.pkgforge.dev/agents). ### Is there a copy of the repositories outside Cloudflare? Yes. Push mirrors copy each repository with its forge state (`refs/githome/meta`) to GitHub, GitLab, Forgejo or Codeberg, and encrypted backups go to an S3-compatible bucket off Cloudflare once its credentials are set. A mirror to Cloudflare Artifacts stays inside Cloudflare. See [Mirrors and backups](https://git.pkgforge.dev/docs/self-hosting/deploy#mirrors-and-backups). ### How do I move a repository from GitHub? Githome's importer copies a repository from GitLab, Forgejo, Gitea or Codeberg on the server, with history, issues, pull requests, reviews, releases and branch protection, keeping their numbers. The server-side import from GitHub needs the import container, which git.pkgforge.dev does not run, so it stops at its Git step with "no import container is configured"; a local import (`githome migrate github --local`) or a GitHub pull mirror brings a GitHub repository in. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). ### Where do I report a bug or ask a question? In the public tracker [Azathothas/issues](https://github.com/Azathothas/issues), with the label `git.pkgforge.dev`. People with an account can report a security problem privately with the [security report form](https://git.pkgforge.dev/security/report); until the deployment has its Turnstile keys, the contact and report forms take messages only from people who are signed in. --- # Git hosting, pull requests and GitHub Actions–compatible CI in one place > What Githome does: Git hosting, pull requests and a merge queue, GitHub Actions–compatible CI (dormant here), a container registry and AI agents. Source: https://git.pkgforge.dev/features (last updated 2026-11-12) Githome is a git forge for teams of people and AI agents. It hosts your repositories, reviews and CI in one place, reads GitHub Actions workflows as they are, and treats AI coding agents as accounts with their own tokens and guardrails. It runs on Cloudflare, with no servers to manage and with copies kept off Cloudflare. This instance is one private forge at git.pkgforge.dev: accounts are by invitation from the superadmin, and anyone can browse and clone public repositories without an account. This page lists what Githome does today, what it doesn't do yet, and where each feature is documented. ## Git hosting - **Clone, fetch and push over HTTPS** with a token or a browser sign-in from the CLI. Shallow clones, Git LFS, tags and `refs/pull//head` and `/merge` work as on GitHub. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). - **Every repository is its own strongly consistent store.** Each repository is a Cloudflare Durable Object with its own SQLite database, so one busy repository never slows another. - **Push protection on by default.** Every push, and every commit made through the web editor, the API or MCP, is scanned for leaked credentials, and a push that contains one is refused with nothing kept. See [Push protection](https://git.pkgforge.dev/docs/security/push-protection). - **Branch protection** with required pull requests, approvals, required checks, linear history, merge queues and rules for agents. See [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection). - **Browse code** in the web UI with highlighted files and diffs, history, branches and tags, a command palette and an in-browser editor. See [Browsing code](https://git.pkgforge.dev/docs/repositories/browsing-code). - **Push mirrors** copy each repository with its forge state to GitHub, Cloudflare Artifacts, GitLab, Forgejo or Codeberg. Backups go to an S3-compatible bucket off Cloudflare once its credentials are set. ## Pull requests, reviews and issues - **Pull requests with intent.** Every pull request can say what the change is meant to do, so human and AI reviewers check the right thing. Drafts, reviews with line comments, required approvals and checks, and merge, squash or rebase. See [Pull requests](https://git.pkgforge.dev/docs/collaboration/pull-requests). - **Auto-merge and a merge queue.** Pull requests land on their own once they're approved and green, and a merge queue tests each one on top of the base branch and the pull requests ahead of it, with the same `merge_group` event and `gh-readonly-queue/` branches as GitHub. See [Merge queue](https://git.pkgforge.dev/docs/collaboration/merge-queue). - **Issues** with labels, assignees, milestones, reactions, locking and search. See [Issues](https://git.pkgforge.dev/docs/collaboration/issues). - **Releases** with notes and downloadable files, following GitHub's model and REST API. See [Releases](https://git.pkgforge.dev/docs/collaboration/releases). - **Checks and commit statuses** from Githome Actions, external CI and bots. See [Checks and commit statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). ## Actions: CI that reads your GitHub workflows The Actions code is part of Githome, and the forge CI of git.pkgforge.dev is dormant: no workflow runs there now, an event starts no run, and a dispatch is refused with "CI is off on this deployment". The pages below are the reference for the workflow syntax Githome reads. - **Drop-in for GitHub Actions.** Githome reads `.github/workflows/*.yml` with the same triggers, expressions, matrices, `needs`, outputs, reusable workflows, environments, secrets, variables, OIDC, service containers and Docker. JavaScript, composite and Docker actions from GitHub are meant to run as they do there. See [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility), which lists every difference. - **Built-in actions.** `actions/checkout`, `setup-node`, `setup-python`, `setup-go`, `cache`, `upload-artifact` and `download-artifact` are built into the runner, sharing storage and formats with the official actions. - **Self-hosted runners** for macOS, Windows, Arm, GPUs or machines on your own network, with `githome runner`. See [Self-hosted runners](https://git.pkgforge.dev/docs/actions/runners#self-hosted-runners). - **Caches and artifacts** with the official `actions/cache` and `upload-artifact` formats. See [Caching and artifacts](https://git.pkgforge.dev/docs/actions/caching-and-artifacts). ## Container registry Push and pull images at `git.pkgforge.dev//` with `docker`, `podman`, `buildx`, `crane` or the `docker/*` actions, instead of ghcr.io. Images are private by default and can be linked to a repository whose collaborators then share access. See [Container registry](https://git.pkgforge.dev/docs/packages/container-registry). ## Built for AI agents - **Agents are accounts.** Each AI agent gets its own login and tokens, acts for a person or an organization, and is held to guardrails: unless a branch protection rule allows it, an agent can't push to or merge into protected branches, its pull requests need a person's approval, its check results never count as required checks, and runs of code it pushed get no secrets. See [Guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails). - **Today and Needs you.** One page, the first after you sign in, with what needs you, what your agents are working on and what merged or failed since yesterday, also as the `today` MCP tool. See [Today](https://git.pkgforge.dev/docs/agents/today). - **Merge on green.** Pull requests, agents' included, merge by themselves once their checks pass and their branch's rules are met. See [Merge on green](https://git.pkgforge.dev/docs/collaboration/merge-on-green). - **An MCP server** at `https://git.pkgforge.dev/mcp`, with OAuth sign-in or an agent token. See [Connect AI apps](https://git.pkgforge.dev/docs/connect). - **Agent tasks, agent review, terminals, projects and sandboxes** run an agent for you in a sandbox: Claude Code, Codex or your own command with your own model key opens a pull request, and another agent reviews pull requests. They are part of the code and dormant on git.pkgforge.dev, because they need the forge CI. See [Agent tasks](https://git.pkgforge.dev/docs/agents/tasks), [Agent review](https://git.pkgforge.dev/docs/agents/review), [Terminals](https://git.pkgforge.dev/docs/agents/terminal), [Projects](https://git.pkgforge.dev/docs/agents/projects) and [Sandboxes](https://git.pkgforge.dev/docs/agents/sandboxes). ![The Today page on Githome: what needs you, the agent pull requests at work, your agent tasks and what changed since yesterday](https://git.pkgforge.dev/docs/images/today.webp) See [Githome for AI agents](https://git.pkgforge.dev/agents) for the whole picture. ## Works with the tools you already use | Tool | How it works with Githome | | --- | --- | | `git` | Standard Git over HTTPS. `githome auth setup-git` signs git in through the browser. Editors clone with the plain HTTPS URL; Githome ships no editor extension. | | GitHub CLI (`gh`) | Works as with GitHub Enterprise Server, through Githome's GitHub-compatible REST and GraphQL APIs. See [Use gh](https://git.pkgforge.dev/docs/agents/github-cli). | | Claude Code | The MCP server, added with `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`. See [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code). | | Codex | The MCP server, added with `codex mcp add githome --url https://git.pkgforge.dev/mcp`. See [Codex](https://git.pkgforge.dev/docs/connect/codex). | | Claude, Cursor and other MCP clients | The MCP server at `/mcp` with a browser sign-in. See [Connect AI apps](https://git.pkgforge.dev/docs/connect). | | Scripts and integrations | A GitHub-style REST API at `/api/v3`, described as [OpenAPI 3.1](https://git.pkgforge.dev/docs/api/openapi.json), and GitHub-compatible [webhooks](https://git.pkgforge.dev/docs/repositories/webhooks). | | The `githome` CLI | Repositories, pull requests, issues, runs, secrets, runners and migrations from a terminal. It needs Node.js 26 or later. See the [CLI reference](https://git.pkgforge.dev/docs/reference/cli). | ## Moving from GitHub A server-side importer brings over a GitLab, Forgejo, Gitea or Codeberg repository with its full Git history, issues, pull requests, reviews, comments, labels, milestones, releases and branch protection, keeping issue and pull request numbers. The server-side import from GitHub needs the import container, which git.pkgforge.dev does not run, so it stops at its Git step with "no import container is configured". To bring in a GitHub repository, use the local import (`githome migrate github --local`) or a GitHub pull mirror. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). ## Security Passkeys instead of passwords, invite-only accounts, branch and push protection, envelope-encrypted secrets, job tokens limited by `permissions:`, signed webhooks and an append-only audit log. See [Security](https://git.pkgforge.dev/security). ## How it runs The service runs on Cloudflare: a Worker serves the web UI, Git, the REST API and MCP; each repository is a Durable Object with SQLite; large objects, caches, artifacts and images live in R2; accounts live in D1; and workflow runs are durable Cloudflare Workflows. The superadmin console is a separate site, `dash.git.pkgforge.dev`, with its own passkey sign-in. See [Built on Cloudflare](https://git.pkgforge.dev/built-on-cloudflare). ## What Githome doesn't do yet Githome is young, and we'd rather you know its limits: - **No forge CI on git.pkgforge.dev.** The Actions code is in Githome and dormant on this host, so no workflow, hosted job, sandbox, task or terminal runs here now. - **HTTPS only for Git.** There's no SSH access. - **No discussions, GitHub Pages-style sites, Codespaces-style cloud editors or app marketplace.** - **No hosted service.** git.pkgforge.dev is one private forge: there is nothing to sign up for, and accounts are made by invitation. --- # Git hosting and CI built for AI coding agents > AI agents get accounts with guardrails, an MCP server, gh and the CLI, Today and merge on green. People decide what lands. Source: https://git.pkgforge.dev/agents (last updated 2026-11-12) Coding agents such as Claude Code and Codex now write a large share of many teams' pull requests. Githome is a git forge designed for that: agents work through the same Git, REST API and MCP server as people, but as accounts of their own, with limits the server enforces, so a person stays in charge of what reaches the main branch. This instance is one private forge at git.pkgforge.dev; accounts are by invitation from the superadmin. Githome has more for agents than accounts: open **Today** in the morning to see what needs you, approve, and let a pull request merge on green. An MCP server, the `githome` CLI and `gh` bring it into the tools you already use. Agent tasks, agent review and sandboxes, which run an agent for you, are part of the code and dormant on git.pkgforge.dev: the forge CI of this host is off, so no sandbox, task or terminal starts here now. | What | In one line | | --- | --- | | [Agent accounts](https://git.pkgforge.dev/agents#agents-are-accounts-not-borrowed-tokens) | Their own logins and tokens, owned by a person or an organization | | [Guardrails](https://git.pkgforge.dev/agents#guardrails-the-server-enforces) | No pushes to protected branches, a person approves, no secrets for agent code | | [Agent tasks](https://git.pkgforge.dev/agents#agent-tasks-a-goal-in-a-pull-request-out) | A goal in, a pull request out, with Claude Code or Codex in a sandbox (dormant here) | | [Agent review](https://git.pkgforge.dev/agents#agent-review-on-every-pull-request) | Inline findings and an Agent review check on every pull request (dormant here) | | [Today and Needs you](https://git.pkgforge.dev/agents#today-what-needs-you) | What needs you and what your agents did since yesterday | | [Merge on green](https://git.pkgforge.dev/agents#merge-on-green) | Agent pull requests land when their checks pass, after a person approves if you want that | | [Integrations](https://git.pkgforge.dev/agents#integrations) | Claude Code, Codex, MCP, the CLI and gh | ## Agents are accounts, not borrowed tokens On most forges an agent acts with a person's token, so its work is indistinguishable from theirs and it can do anything they can. On Githome: - **Each agent has its own login and tokens**, owned by a person or an organization. Every commit it makes is stamped with who it acts for. - **Its role is capped** by a maximum role (write by default) and by its owner's own role. - **It can't sign in to the web UI.** Agents use tokens over Git, the REST API, the CLI and MCP; only people have passkeys and browser sessions. See [Agents](https://git.pkgforge.dev/docs/agents/overview). ## Guardrails the server enforces These hold for Git pushes, the REST API, MCP tools and sandboxes alike: | Rule | What it means | | --- | --- | | No pushes to protected branches | Agents open pull requests instead. A branch protection rule can allow it. | | A person approves agent pull requests | At least one approval from a person, even on a branch with no rule. An agent's approval never counts. | | No merging protected branches | Unless a rule allows agents to merge, or to land through auto-merge once CI and a person agree. | | Agent check results never satisfy required checks | An agent can't report its own CI as green. | | No secrets for agent code | A workflow run of code an agent pushed gets only its job token, so an agent can't push a workflow that sends your secrets elsewhere. | | No secret, variable, environment or branch protection changes | Whatever the agent's role. | | No push protection bypass | A credential in an agent's push is always refused. | The full list is in [Guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails). ## An MCP server for every AI app Githome runs a Model Context Protocol server at `https://git.pkgforge.dev/mcp`. Claude (claude.ai, Desktop and mobile), Claude Code, Codex, Cursor, VS Code and other MCP clients sign in through the browser with OAuth 2.1, or headless with an agent token. Its tools read code, commit files, open, review and merge pull requests, publish releases, import from GitHub and search these docs, all through the same permission checks and guardrails as Git and the REST API. - [Connect AI apps](https://git.pkgforge.dev/docs/connect): one URL and a browser sign-in for Claude, Claude Code, Codex and others. - [MCP tool reference](https://git.pkgforge.dev/docs/reference/mcp-tools): every tool and its arguments, generated from the server. ## gh, Git and the REST API work as agents expect Agents trained on GitHub already know how to use Githome. The GitHub CLI works with Githome as it does with GitHub Enterprise Server (`githome auth setup-gh` signs it in), so `gh pr create` and `gh pr merge` just work, and Claude Code shows the pull request of the branch it's on. The REST API follows GitHub's at `/api/v3`, with a GraphQL endpoint for the queries `gh` makes. See [Use gh with Githome](https://git.pkgforge.dev/docs/agents/github-cli). ## Sandboxes: a machine for every agent A [sandbox](https://git.pkgforge.dev/docs/agents/sandboxes) is a short-lived Linux container with the repository already cloned, driven over MCP or the REST API: run commands, read and write files, build, test and push. Sandboxes are dormant on git.pkgforge.dev with the rest of the forge CI; a request to start one is refused with "CI is off on this deployment". ## Agent tasks: a goal in, a pull request out Give one of your agents a goal. On a deployment where CI is on, Githome starts a sandbox as that agent with the repository checked out, runs Claude Code, Codex or your own command with your own model key, streams its transcript to the task page, then pushes a branch and opens a pull request for a person to review. Your API key never enters the sandbox: each run gets a token that only Githome's model proxy accepts. A task can **plan first** and wait for your approval, run up to four **attempts** side by side for you to pick from, and **verify and land**. On git.pkgforge.dev tasks are dormant. ![An agent task on Githome: the goal, Claude Code running as the acme-coder agent, its transcript with file edits and test runs, and the pull request it opened](https://git.pkgforge.dev/docs/images/agent-task.webp) A [terminal](https://git.pkgforge.dev/docs/agents/terminal) is a shell in your browser with the repository checked out, where Claude Code or Codex runs on your own plan. It is a sandbox too, so it is dormant here as well. See [Agent tasks](https://git.pkgforge.dev/docs/agents/tasks). ## Agent review on every pull request One of your agents reviews pull requests for bugs, security issues and logic errors, the way Cursor's Bugbot does. It runs in a read-only sandbox with the base branch's `REVIEW.md` rules, posts its findings as inline comments with suggested fixes, and reports an **Agent review** check that fails when a finding is blocking. **Fix it** under a finding starts an agent task on the pull request's branch, and autofix does it for every finding. It needs a sandbox, so it is dormant on git.pkgforge.dev. See [Agent review](https://git.pkgforge.dev/docs/agents/review). ![A pull request opened by an agent on Githome, with its intent, the task that wrote it, and an agent review with an inline finding, a suggested fix and a Fix it button](https://git.pkgforge.dev/docs/images/agent-pull-request.webp) ## Today: what needs you [Today](https://git.pkgforge.dev/docs/agents/today) is the first page after you sign in: what needs you (agent pull requests waiting for a person, reviews you were asked for, your own blocked pull requests), what your agents are working on, and what merged, shipped or failed since yesterday, across every repository you can see. Agents read the same view with the `today` MCP tool. ![The Today page on Githome: counts of what needs you, agent pull requests and failed runs, then the Needs you, Agents at work, Your agent tasks and Since yesterday sections](https://git.pkgforge.dev/docs/images/today.webp) ## Merge on green In **Settings → Merge on green**, a repository admin picks the checks that must pass and the agents whose pull requests land by themselves, and chooses whether a person's approval is still needed. Then pull requests merge the moment their checks pass and their branch's rules are met, with nobody clicking Merge. An agent's change to a workflow file still needs a person to merge it. See [Merge on green automatically](https://git.pkgforge.dev/docs/collaboration/merge-on-green). ![The merge box of an agent's pull request on Githome: its required check passed and auto-merge is on, waiting for a person's approval](https://git.pkgforge.dev/docs/images/merge-on-green.webp) ## Projects with shared memory Every repository is also a [project](https://git.pkgforge.dev/docs/agents/projects): a board of its agent tasks, a conversation for the people working on it, instructions every task follows and a memory every task reads. Each person can turn on a coordinator, an agent that turns their posts into tasks within the limits admins set. Every agent feature is optional and off until someone turns it on. People bring their own model keys or subscriptions; Githome doesn't sell or include model access. ## Integrations | Tool | What it adds | How to get it | | --- | --- | --- | | Claude Code | The MCP server. | `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`, then sign in from `/mcp`. See [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code). | | Codex | The MCP server. | `codex mcp add githome --url https://git.pkgforge.dev/mcp`, then `codex mcp login githome`. See [Codex](https://git.pkgforge.dev/docs/connect/codex). | | Any MCP client | The MCP server. | `https://git.pkgforge.dev/mcp`. See [MCP](https://git.pkgforge.dev/docs/agents/mcp). | | Claude (claude.ai, Desktop, mobile) | Githome as a custom connector. | Settings → Connectors → Add custom connector. See [Claude](https://git.pkgforge.dev/docs/connect/claude). | | Terminal | The `githome` CLI: pull requests with intent, auto-merge, runs and logs. `githome setup` signs in and sets up git and gh. | `curl -fsSL https://git.pkgforge.dev/install \| bash`. See [CLI sign-in](https://git.pkgforge.dev/docs/accounts/cli-sign-in). | | GitHub CLI | `gh pr create`, `gh pr merge` and the rest. | `githome auth setup-gh`. See [Use gh](https://git.pkgforge.dev/docs/agents/github-cli). | | Editors | Clone with the plain HTTPS URL of a repository; Githome ships no editor extension. | `githome auth setup-git` lets git push with your Githome sign-in. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). | ## Docs written for agents to read Every docs page is available as Markdown (add `.md` to its URL, or send `Accept: text/markdown`). [/llms.txt](https://git.pkgforge.dev/llms.txt) indexes the site and the docs, [/llms-full.txt](https://git.pkgforge.dev/llms-full.txt) holds all of it in one file, the REST API is described as [OpenAPI 3.1](https://git.pkgforge.dev/docs/api/openapi.json), and agents connected over MCP can call `search_docs` and `read_docs`. See [Docs for AI agents](https://git.pkgforge.dev/docs/agents/docs-for-agents). ## Frequently asked questions ### Which AI coding agents work with Githome? Any agent that uses Git, the GitHub CLI, a REST API or MCP. There are step-by-step guides for Claude, Claude Code, Codex, Cursor and VS Code. ### Can I use my Claude or ChatGPT subscription? In a [terminal](https://git.pkgforge.dev/docs/agents/terminal), on a deployment where CI is on: you sign in to Claude Code or Codex there with your own plan. Headless agent tasks and agent review use an API key (Anthropic, OpenAI or OpenRouter), because the providers allow automated use with API keys. Both are dormant on git.pkgforge.dev. ### Can an agent merge its own pull request? Not by default. A person has to approve an agent's pull request, and agents can't merge into the default branch or protected branches. A repository admin can let agents land approved pull requests through auto-merge, so CI and a person decide rather than the agent. ### Do I need to give Githome my model API key? Only to run agent tasks or agent review with an API key, which need a deployment where CI is on. The key is stored encrypted and never enters the sandbox; runs reach the model through Githome's proxy with a token scoped to that run. Nothing else needs a key. ### Is Githome only for agents? No. People use the same web UI, Git and pull requests as on any forge. Agents are first-class collaborators alongside them. To report a bug or ask a question, use the public tracker at [github.com/Azathothas/issues](https://github.com/Azathothas/issues) with the label `git.pkgforge.dev`. --- # Security built in, not bolted on > How Githome protects code and secrets: passkeys instead of passwords, invite-only accounts, push protection, encrypted secrets, agent guardrails, audit log. Source: https://git.pkgforge.dev/security (last updated 2026-11-12) A forge holds a team's most valuable asset and the keys to its production systems. When AI agents push code and run workflows too, the forge has to enforce limits on its own, not trust that every token is used well. These are the protections every account and repository on Githome gets by default. Githome is a private, internal forge at git.pkgforge.dev, and the [Security overview](https://git.pkgforge.dev/docs/security/overview) documents the model that enforces them. ## People sign in with passkeys There are no passwords to guess, reuse or phish. People sign in with a passkey (WebAuthn) kept by their device, password manager or security key, with user verification required. Passkeys are bound to the domain (`git.pkgforge.dev`), so a look-alike site can't use them. Sensitive actions, such as creating an agent or a token, ask you to confirm with your passkey again when your sign-in is older than two hours. A person who lost their passkeys asks the superadmin for a sign-in link: there is no email recovery and no Cloudflare Access sign-in. See [Passkeys and sign-in](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in). ## Invite-only Githome is invite-only: nobody joins without an invitation from the superadmin, who invites each account in the dash and sends the one-time invitation link by hand. Githome sends no email for an invitation. An invitation to an organization or a repository goes to an existing account. Invite links work once and expire after 14 days. Open sign-up is off on git.pkgforge.dev ([Configuration](https://git.pkgforge.dev/docs/self-hosting/configuration#signup)). The superadmin console is a separate site, `dash.git.pkgforge.dev`, with its own passkey sign-in. Anyone can browse and clone public repositories without an account. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). ## Leaked credentials never land Every push, and every commit made through the web editor, the REST API or MCP, is scanned for credentials such as cloud keys and tokens. A push that contains one is refused, and nothing from it is kept. Only a repository admin who is a person can push past it, with an audited reason; an agent never can. See [Push protection](https://git.pkgforge.dev/docs/security/push-protection). ## Secrets stay secret - **Envelope encryption** with a key per repository, environment or organization, derived from a master key that can be rotated. - **Masked in logs:** secret values are replaced with `***`. - **Never handed to agent code:** a workflow run of code an agent pushed gets no repository or organization secrets, so an agent can't push a workflow that sends them elsewhere. - **Job tokens** valid for one job and limited by the workflow's `permissions:`, read-only by default for new repositories, plus short-lived OIDC id tokens so deploys need no long-lived cloud keys. The forge CI of git.pkgforge.dev is dormant, so no workflow runs there now; these protections are in the Actions code that stays in Githome. See [OIDC](https://git.pkgforge.dev/docs/actions/oidc). ## A human in the loop for agents AI agents are accounts with their own tokens and server-enforced guardrails: no pushes to protected branches, a person's approval on agent pull requests unless a repository waives it, agent check results never counted as required checks, and no secret, variable, environment or branch protection changes. See [Githome for AI agents](https://git.pkgforge.dev/agents) and [Guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails). ## Tokens with limits Personal and agent tokens (`ghome_...`) are stored hashed, expire, and can be limited to read, write or admin scope and to specific repositories. A read token never writes. See [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens). ## Every sensitive action is recorded An append-only audit log records sign-ins, token and agent changes, permission changes, secret changes, push protection bypasses and more, and, where the deployment sends email, security emails tell you when something important changes on your account. See [Audit log](https://git.pkgforge.dev/docs/security/audit-log). ## Isolation Each repository is its own Durable Object with its own database, and the superadmin console is a separate Worker with its own D1 database and its own sign-in. Where the forge CI runs, each workflow job runs in a fresh container thrown away after the job; on git.pkgforge.dev no container starts. The web UI sends a strict, nonce-based Content Security Policy, HSTS with preload and frame protection on every page, and images from other sites in Markdown are fetched through Githome's own proxy, so those sites never see who reads a page. ## Reviewed before release The [Security overview](https://git.pkgforge.dev/docs/security/overview) documents the whole model in detail: identity and tokens, Git and storage, secrets, the agent features and MCP, the web UI and REST API, and the GitHub importer. ## Report a vulnerability If you find a security problem, please tell us privately through the [report form](https://git.pkgforge.dev/security/report), the contact in [`/.well-known/security.txt`](https://git.pkgforge.dev/.well-known/security.txt). Until the deployment has its Turnstile keys, the form takes reports only from people who are signed in. Good-faith research is covered by a safe harbour. See [Reporting a vulnerability](https://git.pkgforge.dev/docs/security/disclosure). --- # Git hosting built on Cloudflare > How Githome runs Git hosting on Cloudflare Workers, Durable Objects, D1, R2, Queues and Workflows, what that means for users, and its limits. Source: https://git.pkgforge.dev/built-on-cloudflare (last updated 2026-11-12) Githome is a private, internal git forge that runs on Cloudflare, at git.pkgforge.dev, with copies kept off Cloudflare. There are no servers, virtual machines or databases behind it that anyone has to run: one Cloudflare Worker and the Cloudflare products it uses serve Git, pull requests, the REST and GraphQL APIs, the MCP server and the container registry. This page explains which Cloudflare product does what, what that means for the people using it, and the limits that come with it. ## Where it runs Githome is deployed by its operator, from a private repository, to one Cloudflare account. It is not a product for sale: there is no hosted service to sign up for, no plan and no price, and accounts are by invitation from the superadmin. The deployment uses the Workers Paid plan, R2, D1, Queues and Workflows, and each part of the instance has its own host: - **`git.pkgforge.dev`** is the core: the web UI, Git, the APIs, MCP, the container registry and the documentation. Anyone can browse and clone public repositories there without an account. - **`dash.git.pkgforge.dev`** is the superadmin console, a Worker of its own with its own passkey sign-in. - **`NAME.git.pkgforge.dev`** is the host of each module, once the module is deployed. Nobody who uses Githome needs a Cloudflare account; people sign in with passkeys. See [Deployment and operation](https://git.pkgforge.dev/docs/self-hosting), [Deploy and update Githome](https://git.pkgforge.dev/docs/self-hosting/deploy), [Configuration](https://git.pkgforge.dev/docs/self-hosting/configuration) and [Architecture](https://git.pkgforge.dev/docs/self-hosting/architecture). ## Which Cloudflare product runs what This is the same mapping as the [Architecture](https://git.pkgforge.dev/docs/self-hosting/architecture) documentation, which goes into more detail. | Cloudflare product | What it runs in Githome | | --- | --- | | Workers | The web UI and the public docs, Git over HTTPS, Git LFS, the REST and GraphQL APIs, the MCP server and the container registry. The Worker holds no state of its own: it signs the caller in, checks their role and hands the request to the right repository. The superadmin console is a second Worker, and each module is another. | | Durable Objects with SQLite, one per repository | Everything inside one repository: branches and tags, git objects, issues, pull requests, reviews, checks and commit statuses, releases, environments, secrets, webhooks and the merge queue. Live pull request updates reach the browser over the object's WebSockets. | | R2 | Anything too large for SQLite: git objects over 512 KiB compressed, Git LFS files, container image layers, release assets and cached source archives. | | D1 | Data that belongs to no single repository: accounts, organizations, tokens, the list of repositories and who can reach them, invitations, notifications, the audit log and the container registry's index. | | Queues | Webhook deliveries and their retries, notifications, audit log entries and email jobs, sent in the background so the request that caused them doesn't wait. | | Workflows | Imports and account exports and deletions, as durable Cloudflare Workflows whose steps and waits survive restarts and deploys. | | Durable Object alarms and Cron Triggers | Housekeeping such as registry cleanup and token expiry reminders, the mirror and backup jobs, and the workflow scheduler. | | Email Sending | Notification and security email, where the deployment has email sending set up. Githome sends no email for an invitation. | The forge CI of git.pkgforge.dev is dormant: the instance starts no Actions run, no hosted job and no Cloudflare Container. The Actions code is part of Githome, and the [Actions documentation](https://git.pkgforge.dev/docs/actions/overview) keeps its reference content. ## How a push moves through it 1. `git push` reaches the Worker, which checks your token and your role on the repository and passes the push to the repository's Durable Object. 2. The object scans every new file for leaked credentials ([push protection](https://git.pkgforge.dev/docs/security/push-protection)), stores the objects (small ones in its SQLite database, large ones in R2), checks branch protection and moves each branch with a compare-and-swap, so two pushes to the same branch are applied one after the other. 3. The object emits a `push` event to the events queue, which writes the audit log entry, delivers webhooks and creates notifications in the background. A push mirror, where one is set up, copies the repository with its forge state to another provider. ## What this means for you - **No servers to run.** The instance is a Worker and the Cloudflare products it binds to, so there is nothing to provision, patch or scale. `gh` and your editor's plain HTTPS clone work as they do with GitHub. - **One busy repository never slows another.** Each repository is its own Durable Object with its own database, the single writer for everything in it, so ref updates and merges are strongly consistent without locks. - **Long work survives restarts.** An import is a durable Workflow, so a deploy or a restart doesn't lose it. - **Mirrored and backed up.** Push mirrors copy each repository, with its forge state in `refs/githome/meta`, to GitHub, Cloudflare Artifacts, GitLab, Forgejo or Codeberg, and backups go to an S3-compatible bucket off Cloudflare once its credentials are set. - **Cloudflare's network.** Requests are answered by the Worker at the Cloudflare location that receives them. A repository's own data lives in its Durable Object, in one place, so pages that read a repository make a trip to wherever that object is. ## Limits that come with building on Cloudflare - **A push carries at most 100 MB.** Use [Git LFS](https://git.pkgforge.dev/docs/repositories/git-lfs) for large files. Container image layers larger than Cloudflare's 100 MB request limit can't be pushed in one request. - **Clones send more bytes than GitHub's.** Packs are sent without deltas, so clones and fetches download more data. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git#limits-and-differences-from-github). - **No Cloudflare Containers in use.** Because the forge CI is dormant, there are no hosted runners and no agent sandboxes on git.pkgforge.dev. Imports from GitLab, Forgejo, Gitea and Codeberg run without a container; the server-side import from GitHub needs the import container and stops at its Git step. - **Per-account quotas.** The superadmin sets quotas for repositories and storage per account. See [Limits](https://git.pkgforge.dev/docs/reference/limits). ## Frequently asked questions ### Does Githome run on Cloudflare? Yes, with copies off Cloudflare. A Cloudflare Worker serves the web UI, Git, the APIs and MCP; each repository is a Durable Object with its own SQLite database; large files live in R2 and accounts in D1; imports are Cloudflare Workflows. See [Architecture](https://git.pkgforge.dev/docs/self-hosting/architecture). ### Can I sign up for Githome? No, accounts are by invitation. The superadmin invites each account in the dash and sends the one-time invitation link by hand. Anyone can browse and clone public repositories without an account. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). ### Does Githome run CI? Not on git.pkgforge.dev. The forge CI is dormant, so no workflow runs there now. The Actions documentation keeps the reference content for the code that stays in Githome. ### Where do I report a bug or ask a question? In the public tracker, [github.com/Azathothas/issues](https://github.com/Azathothas/issues), with the label `git.pkgforge.dev`. Report security problems privately with the [report form](https://git.pkgforge.dev/security/report), which takes reports only from signed-in people until the deployment has its Turnstile keys. --- # About Githome > What Githome is, how it's built on Cloudflare, who can use it at git.pkgforge.dev, and how to reach the people who run it. Source: https://git.pkgforge.dev/about (last updated 2026-11-12) Githome is a private, internal git forge at git.pkgforge.dev. It is compatible with GitHub's API and with `gh`, and it runs on Cloudflare, with copies kept off Cloudflare. Agents do their work through Git and pull requests like everyone else; people see what the agents did, approve what needs them and follow the whole process. Githome is not a product for sale: there is no plan, no price and no hosted service to sign up for. ## Why it exists GitHub was designed for people. Agents on GitHub borrow a person's token, their pull requests look like anyone else's, and the only limits on them are the ones a team remembers to configure. Githome is a forge where an agent is an account of its own with limits the server enforces, and where moving from GitHub costs an afternoon rather than a rewrite: your workflow files stay in the repository (no run starts here while the forge CI is dormant), and `gh` and your editor's plain HTTPS clone keep working. ## How it's built - **On Cloudflare, with no servers.** A Worker serves the web UI, Git, the REST and GraphQL APIs and MCP; every repository is a Durable Object with its own SQLite database; accounts live in D1 and large objects in R2. See [Architecture](https://git.pkgforge.dev/docs/self-hosting/architecture) and [Built on Cloudflare](https://git.pkgforge.dev/built-on-cloudflare). - **Separate hosts for separate jobs.** The core serves `git.pkgforge.dev`. The superadmin console is its own site, `dash.git.pkgforge.dev`, with its own passkey sign-in, and each module will serve `NAME.git.pkgforge.dev` once it is deployed. See [Deployment and operation](https://git.pkgforge.dev/docs/self-hosting). - **Mirrored and backed up.** Push mirrors copy each repository, with its forge state, to GitHub, Cloudflare Artifacts, GitLab, Forgejo or Codeberg, and backups go to an S3-compatible bucket off Cloudflare once its credentials are set. - **The forge CI is dormant.** git.pkgforge.dev starts no Actions run, no hosted job and no agent sandbox. The Actions code is part of Githome, and the [Actions documentation](https://git.pkgforge.dev/docs/actions/overview) keeps its reference content. ## Who can use it Anyone can browse and clone public repositories at git.pkgforge.dev without an account. A write needs an account, and accounts are by invitation: the superadmin invites each one in the dash and sends the one-time invitation link by hand. Githome sends no email for an invitation, and open sign-up is off. People sign in with a passkey. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations) and [Passkeys and sign-in](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in). ## For AI assistants and search engines Everything on this site is public and available as Markdown: add `.md` to any page's address, or send `Accept: text/markdown`. [/llms.txt](https://git.pkgforge.dev/llms.txt) indexes the site and the documentation, and [/llms-full.txt](https://git.pkgforge.dev/llms-full.txt) holds all of it in one file. Every site page shows the date its facts were last checked. ## Contact - **Questions and privacy requests:** the [contact form](https://git.pkgforge.dev/contact), for people with an account. Messages reach the superadmin, who reads them in the dash. - **Bugs and questions about the service:** the public tracker, [github.com/Azathothas/issues](https://github.com/Azathothas/issues), with the label `git.pkgforge.dev`. Without an account, this is the way to reach the people who run the instance: until the deployment has its Turnstile keys, the contact form and the report form take messages only from people who are signed in. - **Security problems:** the private [report form](https://git.pkgforge.dev/security/report), as listed in [`/.well-known/security.txt`](https://git.pkgforge.dev/.well-known/security.txt), for people with an account. - **git.pkgforge.dev status:** [/status](https://git.pkgforge.dev/status). - **Documentation:** [git.pkgforge.dev/docs](https://git.pkgforge.dev/docs). --- # Githome FAQ > Short answers about Githome: who can use it, accounts and sign-in, GitHub compatibility, the dormant forge CI, Cloudflare, AI agents, security and migration. Source: https://git.pkgforge.dev/faq (last updated 2026-11-12) Short, direct answers to the questions people and AI assistants ask most about Githome. Each answer links to the page with the details. ## Frequently asked questions ### What is Githome? Githome is a private, internal git forge at git.pkgforge.dev, compatible with GitHub's API and with `gh`. It hosts Git repositories, pull requests with reviews and a merge queue, issues, releases and a container registry, and gives AI agents accounts of their own with guardrails the server enforces. It runs on Cloudflare, with copies kept off Cloudflare. See [Features](https://git.pkgforge.dev/features) and [About Githome](https://git.pkgforge.dev/about). ### Can I sign up for Githome? No. Githome is not a product for sale, and there is no hosted service to sign up for and no plan or price. Accounts are by invitation: the superadmin invites each account in the dash and sends the one-time invitation link by hand, and Githome sends no email for an invitation. Open sign-up is off on git.pkgforge.dev. Anyone can browse and clone public repositories without an account; a write needs an account. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). ### Can I deploy my own copy? No. The repository of Githome is private, and there is no public clone URL. The docs describe how the instance at git.pkgforge.dev is deployed and configured, so that its operator and its users can reason about it: see [Deployment and operation](https://git.pkgforge.dev/docs/self-hosting) and [Deploy and update Githome](https://git.pkgforge.dev/docs/self-hosting/deploy). ### Where do I report a bug or ask a question? In the public tracker, [github.com/Azathothas/issues](https://github.com/Azathothas/issues), with the label `git.pkgforge.dev`. Githome takes no pull requests from visitors. For a question to the people who run the instance, use the [contact form](https://git.pkgforge.dev/contact) if you have an account: until the deployment has its Turnstile keys, the contact form and the [security report form](https://git.pkgforge.dev/security/report) take messages only from people who are signed in. Without an account, ask in the public tracker. The messages reach the superadmin. ### Is Githome a GitHub alternative? For the teams that use it, yes: Githome replaces GitHub's code hosting and pull requests. It doesn't have GitHub's app marketplace, Codespaces, Pages or Discussions, and its forge CI is dormant. See [Features](https://git.pkgforge.dev/features). ### Does Githome run CI? Not on git.pkgforge.dev. The forge CI is dormant: an event starts no Actions run, and a dispatch, a sandbox or a terminal is refused with "CI is off on this deployment". No hosted job runs there and no Cloudflare Container starts. The Actions code is part of Githome, and the [Actions documentation](https://git.pkgforge.dev/docs/actions/overview) keeps its reference content: syntax, expressions, events and permissions. Each of those pages notes that no workflow runs on git.pkgforge.dev now. ### Do GitHub Actions workflow files work on Githome? The syntax, expressions, matrices, reusable workflows, environments, secrets, variables and OIDC are implemented, and every difference from GitHub is listed in [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). Because the forge CI of git.pkgforge.dev is dormant, no workflow runs there now. Your workflow files stay in the repository. ### Does Githome have macOS, Windows or Arm runners? No hosted ones, and none run on git.pkgforge.dev while the forge CI is dormant. Self-hosted runners are described in [Runners](https://git.pkgforge.dev/docs/actions/runners). ### Does Githome run on Cloudflare? Yes, with copies off Cloudflare (push mirrors, and backups once their bucket is set). A Cloudflare Worker serves the web UI, Git, the REST and GraphQL APIs and MCP; each repository is a Durable Object with its own SQLite database; large files are in R2 and accounts in D1; imports are Cloudflare Workflows. The superadmin console is its own site, `dash.git.pkgforge.dev`, and each module will serve `NAME.git.pkgforge.dev` once it is deployed. See [Built on Cloudflare](https://git.pkgforge.dev/built-on-cloudflare). ### Which AI coding agents work with Githome? Any agent that uses Git, the GitHub CLI, a REST API or MCP. Githome gives agents the MCP server at `https://git.pkgforge.dev/mcp` (browser sign-in, or a bearer token), the `githome` CLI, `gh` against the core, agent tokens and guardrails. Claude Code: `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`. Codex: `codex mcp add githome --url https://git.pkgforge.dev/mcp`. claude.ai connects through a connector. Githome ships no editor extension, no Claude Code or Codex plugin and no plugin marketplace, and an editor clones with the plain HTTPS URL. See [Connect AI apps](https://git.pkgforge.dev/docs/connect) and [Githome for AI agents](https://git.pkgforge.dev/agents). ### Does Githome have an MCP server? Yes, at `https://git.pkgforge.dev/mcp`, with browser sign-in (OAuth 2.1) or an agent token. Its tools read code, commit files, open, review and merge pull requests and start imports, under the same permission checks and guardrails as Git and the REST API. The tools that start work (a dispatch, a re-run, a sandbox) answer "CI is off on this deployment"; the tools that read workflow runs and job logs answer from stored data. See [MCP server](https://git.pkgforge.dev/docs/agents/mcp). ### Can an AI agent merge its own pull request? Not by default. Agents are accounts of their own: unless a branch protection rule allows it, they can't push to or merge into the default branch or protected branches, their pull requests need a person's approval, and their check results never satisfy required checks. See [Guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails). ### How do I move from GitHub? Githome's server-side importer copies a GitLab, Forgejo, Gitea or Codeberg repository with its full Git history, issues and pull requests (keeping their numbers), reviews, comments, labels, milestones, releases and branch protection, without a container. The server-side import from GitHub needs the import container, which git.pkgforge.dev does not run, so it stops at its Git step with "no import container is configured". For GitHub, use the local import (`githome migrate github --local`) or a GitHub pull mirror. Secret values can't be copied, so you enter them once. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). ### Can I keep a copy on GitHub? Yes. Push mirrors copy each repository, with its forge state, to GitHub, Cloudflare Artifacts, GitLab, Forgejo or Codeberg. See [Mirrors and backups](https://git.pkgforge.dev/docs/self-hosting/deploy#mirrors-and-backups). ### Does the GitHub CLI work with Githome? Yes. `gh` works with Githome as it does with GitHub Enterprise Server: after `githome auth setup-gh`, commands such as `gh pr create` and `gh pr merge` work in a Githome clone. See [Use gh with Githome](https://git.pkgforge.dev/docs/agents/github-cli). ### Does Githome work with VS Code, Cursor and JetBrains IDEs? Githome ships no editor extension and no JetBrains plugin. An editor clones with the plain HTTPS URL of the repository, with a token as the password. ### Does Githome support Git LFS? Yes. Githome has a built-in Git LFS server, so `git lfs push`, `git lfs pull` and clones of repositories that use LFS work as they do with GitHub. See [Git LFS](https://git.pkgforge.dev/docs/repositories/git-lfs). ### Does Githome have a container registry? Yes. Push and pull images at `git.pkgforge.dev//` with `docker`, `podman`, `buildx` or `crane`. Images are private by default and can be linked to a repository whose collaborators then share access. See [Container registry](https://git.pkgforge.dev/docs/packages/container-registry). ### What doesn't Githome do yet? Git works over HTTPS only, with no SSH. There are no discussions, Pages-style sites, Codespaces-style cloud editors or app marketplace, and the forge CI is dormant. See [What Githome doesn't do yet](https://git.pkgforge.dev/features#what-githome-doesnt-do-yet). ### How do people sign in, and how are secrets protected? People sign in with passkeys; there are no passwords, no email recovery and no Cloudflare Access sign-in. A person who lost their passkeys asks the superadmin for a sign-in link. Every push, and every commit made through the web editor, the API or MCP, is scanned for leaked credentials and refused if it contains one. Stored secrets are encrypted with a key per repository, environment or organization, and an append-only audit log records sensitive actions. See [Security](https://git.pkgforge.dev/security). ### Is Githome SOC 2 certified? No. Githome is a private, internal instance, not a service for sale, so there is nothing to certify. The [Security overview](https://git.pkgforge.dev/docs/security/overview) documents the whole security model. See [Security](https://git.pkgforge.dev/security). ### How do I contact the people who run Githome? If you have an account, use the [contact form](https://git.pkgforge.dev/contact) at git.pkgforge.dev/contact, or the [security report form](https://git.pkgforge.dev/security/report) for security problems; the messages reach the superadmin. Until the deployment has its Turnstile keys, both forms take messages only from people who are signed in, so without an account use the [public tracker](https://github.com/Azathothas/issues) with the label `git.pkgforge.dev`. See [Contact form](https://git.pkgforge.dev/docs/admin/contact-form). ### How do people join? Accounts are by invitation from the superadmin, who sends the one-time invitation link by hand; Githome sends no email for an invitation. An invitation to an organization goes to an existing account. Open sign-up is off on git.pkgforge.dev. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations) and [Configuration](https://git.pkgforge.dev/docs/self-hosting/configuration#signup). --- # Privacy policy > What personal data git.pkgforge.dev and the Githome CLI, editor extensions and agent plugins handle, who processes it, and how long it is kept. Source: https://git.pkgforge.dev/privacy (last updated 2026-10-26) This policy covers **git.pkgforge.dev**, the website and Githome instance that Codician runs, and the Githome **CLI, editor extensions and AI-agent plugins** that Codician publishes. It explains what personal data they handle, why, who processes it, how long it is kept, and what you can ask of us. **The short version:** we collect what git.pkgforge.dev needs to work, we don't sell data, we don't show ads, and there are no analytics or tracking cookies. If you run Githome yourself, your instance's data stays on your own Cloudflare account, and Codician never receives it. Codician ("we") is responsible for the data described here. Contact: **hi@codician.com**. ## If you run your own Githome Githome is open-source software (Apache-2.0). When you deploy it to your own Cloudflare account, you, not Codician, decide what your instance collects and keep all of its data: accounts, repositories, logs and everything else stay on your Cloudflare account. The software doesn't send usage data or telemetry to Codician. Each instance does tell search engines about its own public pages through IndexNow; you can turn that off ([Search engines](https://git.pkgforge.dev/docs/admin/site-administration#search-engines)). This policy doesn't cover instances run by other people; ask whoever runs yours. ## The CLI, editor extensions and AI-agent plugins The `githome` CLI, the VS Code and JetBrains extensions, and the Claude Code and Codex plugins talk only to the Githome instance you set them up for (git.pkgforge.dev unless you choose another). They sign you in to that instance and send it the requests you make, such as listing pull requests or reading a job log. They send nothing to Codician or anyone else. Your token is kept on your computer: in the CLI's config file, your editor's secret storage, or the place your agent app keeps sign-ins. Downloading the CLI, an extension or a plugin from git.pkgforge.dev is an ordinary web request, handled as described under [Visiting the website](https://git.pkgforge.dev/privacy#visiting-the-website). Marketplaces you install from (the Visual Studio Marketplace, Open VSX, the JetBrains Marketplace or a plugin directory) handle your data under their own policies. ## Visiting the website Anyone can read git.pkgforge.dev's public pages, documentation and public repositories without an account. For those visits we don't collect personal data beyond what any web server handles: - **Cloudflare**, which hosts git.pkgforge.dev, processes your IP address, browser user agent and the pages you request to serve the site and protect it from attacks. Our request logs are kept for up to 7 days. - **No analytics or advertising.** There are no analytics scripts, tracking pixels or third-party marketing tools on git.pkgforge.dev. - **Star on GitHub buttons** are plain links. git.pkgforge.dev's server reads the star count from GitHub, so your browser contacts GitHub only if you follow one. ### Cookies git.pkgforge.dev sets only cookies it needs to work. None are used for advertising or to follow you across sites, so there's no cookie banner. | Cookie | What it does | How long | | --- | --- | --- | | `__Host-ghome_session` | Keeps you signed in | 30 days, or until you sign out | | `__Host-ghome_webauthn` | Holds the passkey challenge while you sign in | 5 minutes | | `__Host-ghome_access` | Marks the email recovery that you started in this browser, where the instance offers it | 15 minutes | | `__Host-ghome_csrf` | Protects forms against cross-site request forgery | 30 days | | `__Host-ghome_d1` | Lets the database show you your own changes straight away | 1 day | | `__Host-ghome_flash` | Shows a one-time message after an action | 1 minute | | `__Host-ghome_theme` | Remembers light or dark appearance if you choose one | 400 days | | `__Host-today_collapsed` | Remembers which sections of the Today page you folded | 1 year | ## Forms anyone can use - **Early access requests** (`/early-access`): the email address you give and, if you fill them in, your name, company, what you'd use Githome for and where you host code today. Unconfirmed requests are deleted after 7 days; confirmed ones are kept until a site administrator deletes the request, and you can delete yours yourself at any time. To enforce daily limits, we keep a hashed form of your IP address and of the email address you typed for one day. Details: Early access. - **Contact messages** (`/contact`): your name, the email address you give (or your account's, if you're signed in), the topic and your message, and a note our site administrators may add about how they answered. Only git.pkgforge.dev's site administrators can read messages, and we use them only to reply. If you aren't signed in, your message waits until you confirm your address with the link we email you; unconfirmed messages are deleted after 7 days, unread. Messages marked as spam are deleted after 30 days, and answered ones 365 days after we mark them handled. For daily limits, we keep a hashed form of your IP address and of the email address you typed for one day. Details: [Contact form](https://git.pkgforge.dev/docs/admin/contact-form). - **Security reports** (`/security/report`): what you write, and the email address you give for a reply if you aren't signed in. Only git.pkgforge.dev's site administrators can read reports. - People who aren't signed in pass a **Cloudflare Turnstile** check on these forms, which Cloudflare runs using signals from your browser. ## Accounts on git.pkgforge.dev git.pkgforge.dev is invite-only: accounts are for the people working on Githome. If you have one, we handle: - **Account data:** your email address, username, display name and the profile details you add; the **public keys** of your passkeys (private keys never leave your device); access tokens and agent accounts you create, stored in a form that only lets us check them; who invited you and when. - **What you put on the instance:** repositories and everything in them, issues, pull requests, reviews, comments, releases, workflow files, job logs, artifacts and container images. Git commits carry the author name and email address configured in git; in a public repository they are public. - **Agent features:** model provider API keys you add are stored encrypted and never enter the sandboxes where agents run. When you start an agent task, review or sandbox, the prompts, code and command output the agent needs go to **the model provider you chose** (such as Anthropic or OpenAI), under your own account with that provider and its own terms and privacy policy. Githome keeps each task's transcript, visible to people with write access to the repository, and a record of the tokens each run used, so it can show usage and enforce budgets. - **Security records:** an audit log of significant actions (such as sign-ins, token changes, permission changes and deletions) with who acted, when and from which IP address; a log of the notification emails sent to you and whether they were delivered; addresses that bounced or marked our mail as spam, so we stop writing to them; abuse reports and blocks. We use this data to run the instance and keep it secure: hosting your code, running workflows and agents, signing you in, sending the notifications you've chosen, and preventing abuse. Where laws such as the GDPR apply, the legal bases are providing the service you signed up for and our legitimate interest in keeping it secure. **We don't use your private content to train machine-learning models.** ## Who processes the data - **Cloudflare, Inc.** hosts git.pkgforge.dev and stores its data: Workers, Durable Objects, D1, R2, Queues, Containers (CI runners and agent sandboxes), Email Sending (notifications) and Turnstile. Data isn't pinned to one country: Cloudflare places it and runs jobs in its data centers around the world, and transfers rely on the Standard Contractual Clauses in Cloudflare's data processing terms. - **The model provider you choose** for agent features, as described above. - **Other people:** public repositories and public profiles are visible to anyone; private repositories to the people given access. - **Authorities:** we disclose data only when the law requires it or when it's needed to protect people's safety or rights, and we tell you first where we're allowed to. We don't sell or rent personal data, and we don't share it for advertising. ## How long data is kept | Data | Kept | | --- | --- | | Request logs (with IP addresses) | Up to 7 days | | Sign-in sessions | 30 days, or until you sign out | | Notification email log | 90 days | | Job logs | 90 days | | Workflow artifacts | 1 to 90 days, as the workflow sets (90 by default) | | Account data exports | 7 days | | Contact messages | 7 days unconfirmed; 30 days once marked spam; 365 days after they are answered | | Audit log | 2 years | | Database backups | 30 days of point-in-time recovery | | Username of a deleted account | Not reusable for 90 days | | Your account, content and provider keys | Until you delete them or your account | ## Your choices and rights - **See and export your data:** under **Settings → Account**, download an archive with your profile, settings, repositories (as git bundles) and the issues, comments and reviews you wrote. See [Exporting and deleting your account](https://git.pkgforge.dev/docs/accounts/account-data). - **Correct it:** edit your profile and email address in your settings. - **Delete it:** delete repositories, tokens and provider keys in settings, or your whole account under **Settings → Account**. Commits, issues and comments you made in other people's repositories stay part of those repositories, shown as written by a deleted user, and the audit log keeps what your account did. - **Anything else:** write to **hi@codician.com** to ask for a copy of your data, to object to or restrict a use of it, or with any question. We answer within one month. Depending on where you live, you can also complain to your data protection authority. ## Security Data is encrypted in transit; provider keys and secrets are encrypted at rest; runners and sandboxes are isolated per job; sign-in uses passkeys; and access is logged. See [Security](https://git.pkgforge.dev/security). Please report vulnerabilities through [the private report form](https://git.pkgforge.dev/security/report), never a public issue. ## Children git.pkgforge.dev is not meant for children, and its accounts are for the people working on Githome. ## Changes We'll update this page when what we do changes and change the date at the top. If a change matters to people with accounts, we'll tell them by email before it takes effect. ## Contact Codician, **hi@codician.com**, or the [contact form](https://git.pkgforge.dev/contact). Security reports: [git.pkgforge.dev/security/report](https://git.pkgforge.dev/security/report). --- # Overview > What Githome is, how it fits together, and where to start, whether you are a person, a team moving from GitHub or an AI agent. Source: https://git.pkgforge.dev/docs Githome is a private git forge for people and AI agents, running on Cloudflare at `https://git.pkgforge.dev`. It hosts git repositories, pull requests with reviews and a merge queue, issues, a container registry, a GitHub-style REST API and an MCP server for agents. It also holds GitHub-Actions-compatible CI, which is dormant on git.pkgforge.dev: no workflow runs there now. A server-side importer brings over a repository from GitLab, Forgejo, Gitea or Codeberg, with its history, issues, pull requests, reviews and releases; the server-side import from GitHub needs the import container, which git.pkgforge.dev does not run, so a GitHub repository comes in through the local import (`githome migrate github --local`) or a GitHub pull mirror (see [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github)). ## Start here | If you want to | Read | | --- | --- | | Get set up and push your first repository | [Quickstart](https://git.pkgforge.dev/docs/quickstart) | | Understand accounts, roles, agents and runs | [Concepts](https://git.pkgforge.dev/docs/concepts) | | Move a project from GitHub (the local import, `githome migrate github --local`) or from another forge (**Settings → Imports**) | [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github) | | Read how CI works (dormant on git.pkgforge.dev: no workflow runs there now) | [Actions overview](https://git.pkgforge.dev/docs/actions/overview) and [Workflow syntax](https://git.pkgforge.dev/docs/actions/workflow-syntax) | | Connect Claude, Claude Code, Codex or another AI app (one URL, a browser sign-in) | [Connect AI apps](https://git.pkgforge.dev/docs/connect) | | Run your own AI agents on Githome, with their own accounts and tokens | [Agents](https://git.pkgforge.dev/docs/agents/overview) and [MCP](https://git.pkgforge.dev/docs/agents/mcp) | | Give an agent a goal and get a pull request back, with your own model key (dormant: the forge CI is off) | [Agent tasks](https://git.pkgforge.dev/docs/agents/tasks) | | See the tokens and cost your agent tasks and reviews used | [Usage and cost](https://git.pkgforge.dev/docs/agents/tasks#usage-and-cost) | | Pay for an organization's agents with its own keys, and set what they may use (dormant: the forge CI is off) | [Agents in organizations](https://git.pkgforge.dev/docs/agents/organizations) | | Work in a browser shell with Claude Code or Codex (dormant: the forge CI is off) | [Terminals](https://git.pkgforge.dev/docs/agents/terminal) | | Track agent work on a board, with shared memory and project instructions | [Projects](https://git.pkgforge.dev/docs/agents/projects) | | See what needs you and what your agents did since yesterday | [Today](https://git.pkgforge.dev/docs/agents/today) | | Have one of your agents review pull requests for bugs, like Bugbot (dormant: the forge CI is off) | [Agent review](https://git.pkgforge.dev/docs/agents/review) | | Script against Githome | [REST API guide](https://git.pkgforge.dev/docs/reference/rest-api), [REST API reference](https://git.pkgforge.dev/docs/api) and [CLI reference](https://git.pkgforge.dev/docs/reference/cli) | | Export your data or delete your account | [Exporting and deleting your account](https://git.pkgforge.dev/docs/accounts/account-data) | | Check whether Githome is up | [Status page](https://git.pkgforge.dev/docs/self-hosting/status-page) | | Administer githome (the superadmin, in the dash at `https://dash.git.pkgforge.dev`) | [Site administration](https://git.pkgforge.dev/docs/admin/site-administration) | | Report a security problem privately (the [report form](https://git.pkgforge.dev/security/report)) | [Reporting a vulnerability](https://git.pkgforge.dev/docs/security/disclosure) | ## What you get - **Git hosting.** Clone, fetch and push over HTTPS with a token. Shallow clones, Git LFS and `refs/pull//head` and `/merge` work as on GitHub. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). - **Pull requests and issues.** Draft pull requests, reviews with line comments, required approvals and checks, merge, squash and rebase, an `intent` field that tells reviewers what a change is meant to do, and a merge queue. See [Pull requests](https://git.pkgforge.dev/docs/collaboration/pull-requests) and [Merge queue](https://git.pkgforge.dev/docs/collaboration/merge-queue). - **Actions.** Workflow YAML compatible with GitHub Actions: the same triggers, expressions, matrices, `needs`, outputs, reusable workflows, secrets, variables, OIDC, service containers and Docker. The forge CI of git.pkgforge.dev is dormant, so no workflow runs there now. See [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). - **Container registry.** Push and pull images at `git.pkgforge.dev//` instead of ghcr.io. See [Container registry](https://git.pkgforge.dev/docs/packages/container-registry). - **Agents as first-class accounts.** Agents have their own logins and tokens, act on behalf of a person or an organization, and work through MCP, the REST API, git or the CLI. Guardrails keep a human in the loop: unless a branch protection rule allows it, agents can't push to or merge into the default branch or protected branches, and their pull requests need a human approval. [Agent tasks](https://git.pkgforge.dev/docs/agents/tasks) and [agent review](https://git.pkgforge.dev/docs/agents/review) need the forge CI, which is dormant here, and [Today](https://git.pkgforge.dev/docs/agents/today) shows what needs you and what your agents did. See [Agents](https://git.pkgforge.dev/docs/agents/overview). - **Security by default.** Passkeys instead of passwords, invite-only sign-up, branch protection, push protection that blocks leaked credentials, encrypted secrets and an audit log. See [Security overview](https://git.pkgforge.dev/docs/security/overview). ## How Githome runs Githome runs on Cloudflare, with copies kept off Cloudflare and no servers to manage: a Worker serves the web UI, git, the API and MCP; each repository is a Durable Object with its own SQLite database; large objects live in R2; and accounts live in D1. Githome starts no Cloudflare Container. See [Architecture](https://git.pkgforge.dev/docs/self-hosting/architecture). ## Ways to work with Githome | Interface | Best for | Where | | --- | --- | --- | | Web UI | Browsing code, reviewing, settings | `https://git.pkgforge.dev` | | git | Code | `https://git.pkgforge.dev//.git` | | CLI | Terminals and scripts | [`githome`](https://git.pkgforge.dev/docs/reference/cli) | | REST API | Integrations, GitHub-compatible tools | `https://git.pkgforge.dev/api/v3`, see [the reference](https://git.pkgforge.dev/docs/api) | | MCP | AI apps and agents | `https://git.pkgforge.dev/mcp`, see [Connect AI apps](https://git.pkgforge.dev/docs/connect) and [the tools](https://git.pkgforge.dev/docs/reference/mcp-tools) | | Webhooks | Reacting to events elsewhere | [Webhooks](https://git.pkgforge.dev/docs/repositories/webhooks) | ## For AI agents reading these docs Every page is available as plain Markdown: add `.md` to its URL, or send `Accept: text/markdown`. [/llms.txt](https://git.pkgforge.dev/llms.txt) indexes every page, [/llms-full.txt](https://git.pkgforge.dev/llms-full.txt) holds all of them in one file, and [/docs/api/openapi.json](https://git.pkgforge.dev/docs/api/openapi.json) describes the REST API. Agents connected over MCP can call `search_docs` and `read_docs`. See [Docs for AI agents](https://git.pkgforge.dev/docs/agents/docs-for-agents). ## Access Githome is invite-only, and open sign-up is off. You join from the link of an instance invite, which the superadmin makes in the dash and sends you by hand; githome sends no email for it. You sign in with a passkey, and a person who lost their passkeys asks the superadmin for a sign-in link. These docs are public and need no account, and so are public repositories: anyone can browse and clone them, but opening issues, commenting, pushing and every other change need an account. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). A bug or a question goes to the public tracker [Azathothas/issues](https://github.com/Azathothas/issues) with the label `git.pkgforge.dev`. --- # Quickstart > Go from an invite to a working Githome repository: passkey, CLI sign-in, first push, pull request, release and an AI agent over MCP. Source: https://git.pkgforge.dev/docs/quickstart This guide takes you from an invite link to a repository with code, a merged pull request, a first release and an AI agent connected over MCP. It takes about 15 minutes. Each step shows the web UI and, where it exists, the `githome` CLI and the REST API. The examples use the organization `acme`, the repository `acme/website`, the user `diffy` and the agent `review-bot`, on githome at `https://git.pkgforge.dev`. Replace the names with your own. ## What you need - An account on githome, which is invite-only: the superadmin makes the invite in the dash (`https://dash.git.pkgforge.dev`) and sends you the link by hand. githome sends no email for it, and open sign-up is off. Anyone can browse and clone public repositories without an account. - A browser that supports passkeys (current Chrome, Safari, Edge or Firefox). - Git 2.26 or newer (`git --version`). ## 1. Join with your invite and create a passkey Githome has no passwords. You sign in to the web UI with a passkey, which your device, phone or password manager stores and unlocks with your fingerprint, face or screen lock. 1. Open the whole invite link that the superadmin sent you (`https://git.pkgforge.dev/invite/...#proof=...`). Invite links work for 14 days. 2. On **Join Githome**, check the **Username** (filled in from your email address) and optionally add a **Display name**. Your repositories will live at `https://git.pkgforge.dev//...`. 3. Click **Create a passkey and join** and complete your browser's prompt. You are signed in, and you land on your dashboard. Next time, sign in at `https://git.pkgforge.dev/login` with **Sign in with a passkey**. > **Note:** Add a second passkey on another device, or keep the passkey in a password manager that syncs, under **Settings → Passkeys and sessions**. See [Passkeys and sign-in](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in). ## 2. Install the CLI and sign in Install the `githome` command-line client. On Linux and macOS: ```sh curl -fsSL https://git.pkgforge.dev/install | bash ``` On Windows, in PowerShell: ```powershell powershell -c "irm https://git.pkgforge.dev/install.ps1 | iex" ``` The script puts the CLI in `~/.githome` and adds it to your `PATH`. The CLI needs Node.js 26 or later. The script uses yours when you have one, and otherwise installs a private copy of the Node.js 26 LTS from nodejs.org. See [Install and sign in to the CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in). Sign in through your browser and let Git (and the GitHub CLI, if you have it) use the same sign-in: ```sh githome setup # opens git.pkgforge.dev; click Authorize githome whoami # prints diffy ``` `githome setup` runs `githome login`, then `githome auth setup-git`, so `git clone`, `fetch` and `push` to git.pkgforge.dev use the sign-in, and `githome auth setup-gh` when `gh` is installed. It adds no plugin to any editor or agent. You can run those steps yourself instead. The sign-in opens an **Authorize the Githome CLI** page showing your computer's name. Check it, keep **Write** access for this guide, and click **Authorize**. The terminal prints `✓ Logged in to https://git.pkgforge.dev as diffy`. No token to copy: the CLI gets its own, valid for 90 days and listed under **Settings → Access tokens**, and `githome logout` revokes it. On a machine without a browser (over SSH, for example), `githome setup` prints a code to enter at `https://git.pkgforge.dev/login/device` from any device instead. Working in an editor? Clone with the plain HTTPS URL of the repository (`https://git.pkgforge.dev//.git`), as in the steps below. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). ## 3. Tokens for scripts Scripts and plain Git without the CLI authenticate with a personal access token. 1. Go to **Settings → Access tokens** (`https://git.pkgforge.dev/settings/tokens`). 2. Under **Create a token**, enter a **Name** (for example `ci`), keep **Expires in (days)** at 90 (1 to 366), and pick a **Scope**: | Scope | Allows | | --- | --- | | **Read** | Clone, fetch and view only. Every change is refused (`this token needs the write scope`). | | **Write** (default) | Push, issues, pull requests, releases, runs and creating repositories (up to the maintain role). | | **Admin** | Everything you can do, including repository settings and secrets, and creating organizations, agents, invitations and other tokens. | Leave **Restrict to repositories** empty, or pick the repositories the script needs. 3. Click **Create token** and copy the token. It starts with `ghome_` and is shown only once. Where the deployment sends email, Githome emails you whenever a token is created on your account, including by a CLI sign-in. See [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens). The `GITHOME_TOKEN` and `GITHOME_URL` environment variables give the CLI a token without signing in, which is handy in scripts; `githome login --token ghome_...` saves one. Without the CLI, Git asks for a username and password: enter any username and the token as the password. ## 4. Create a repository Pick one of these. **Web UI.** Click **+** in the header (or open `https://git.pkgforge.dev/new`). Choose the **Owner** (you or an organization such as `acme`), enter the **Repository name** `website`, an optional **Description**, the **Visibility** (**Private** is the default) and the **Default branch** (`main`). Click **Create repository**. **CLI.** ```sh githome repo create website --org acme --private -d "Marketing site" ``` **REST API.** ```sh curl -X POST https://git.pkgforge.dev/api/v3/orgs/acme/repos \ -H "Authorization: Bearer ghome_..." \ -H "content-type: application/json" \ -d '{"name": "website", "description": "Marketing site", "visibility": "private"}' ``` Leave out `--org acme` (or use `POST /api/v3/user/repos`) to create it in your own account. See [Repositories](https://git.pkgforge.dev/docs/repositories/overview). ## 5. Push your code To bring over a repository that lives on GitHub, import it instead of pushing: `githome migrate github acme/website --local --to acme/website`. On git.pkgforge.dev the server-side import from GitHub (**Settings → Imports**) needs the import container, which is not running, so it stops at its Git step with "no import container is configured". The local import runs on your machine instead: it copies branches, tags, the default branch, variables and secret names (secret names only, never values), and with `--issues` also labels, issues, comments and open pull requests, created anew. Imports from GitLab, Forgejo, Gitea and Codeberg run on the server and copy the history, issues and pull requests with their numbers. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). From an existing project: ```sh cd website git remote add origin https://git.pkgforge.dev/acme/website.git git push -u origin main ``` Or start from scratch: ```sh mkdir website && cd website echo "# website" > README.md git init -b main git add README.md git commit -m "first commit" git remote add origin https://git.pkgforge.dev/acme/website.git git push -u origin main ``` Open `https://git.pkgforge.dev/acme/website` to see the files (with syntax highlighting) and the rendered README. Every push is checked for leaked credentials, and so is every commit made in the web editor, through the REST API or over MCP. If you accidentally commit an API key or private key, the push is rejected with `Push blocked: possible secrets detected.` and nothing from it is stored: remove the secret from your commits and push again. See [Push protection](https://git.pkgforge.dev/docs/security/push-protection) and [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). ## 6. Workflows > The forge CI of git.pkgforge.dev is dormant: no run starts there now, so a workflow you push shows no run. Githome keeps the code that reads GitHub Actions workflows from `.github/workflows/`, and this step shows what such a file looks like. Do not expect a run, a log or a check from it on git.pkgforge.dev. A workflow file looks like this: ```yaml # .github/workflows/ci.yml name: CI on: push: branches: [main] pull_request: jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Show what we are building run: | echo "Event: ${{ github.event_name }}, commit: ${{ github.sha }}" ls -la ``` Pushing such a file starts no run on git.pkgforge.dev, and a workflow dispatch is refused with "CI is off on this deployment". Where the CI is on, a run reports a check named `CI / test` (workflow name, then job name) on the commit, which you can require in branch protection. Another CI system can report its results on the same commits as commit statuses or check runs through the GitHub-compatible REST API, and that works here; see [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). Where the CI is on, a run with a syntax error fails and shows the errors; `githome workflow validate` checks files before you push. See [Actions](https://git.pkgforge.dev/docs/actions/overview). Each job gets a `GITHUB_TOKEN` that follows GitHub's `permissions:` model. In a new repository it can only read the code and packages (`contents: read`, `packages: read`), which is all the checkout above needs. A workflow that comments on pull requests, pushes or publishes releases has to ask for more, for example: ```yaml permissions: contents: write pull-requests: write ``` A repository admin can also change the default. See [Workflow permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions). ## 7. Open a pull request Make a change on a branch and push it: ```sh git switch -c update-readme echo "Our marketing site." >> README.md git commit -am "Describe the project" git push -u origin update-readme ``` The push output includes a link: `Create a pull request for 'update-readme':` followed by the compare URL. **Web UI.** Open that link (or the repository's **Pull requests** tab, then **New pull request**). On the compare page, fill in: - **Title**, - **Intent**: one or two sentences on what the change is meant to do, for human and AI reviewers, - **Description** (Markdown), then click **Create pull request**. **CLI.** ```sh githome pr create --title "Describe the project" \ --intent "Add a one-line description of the site to the README." \ --body "Small docs change." ``` Checks that other tools report appear on the pull request (no `pull_request` workflow runs here, because the forge CI is dormant). When nothing blocks it, merge it with **Merge pull request** (choose **Create a merge commit**, **Squash and merge** or **Rebase and merge (fast-forward)**), or: ```sh githome pr merge 1 --squash --delete-branch ``` Teammates review with **Approve** or **Request changes** on the pull request, or `githome pr review 1 --approve`. You can't approve your own pull request. To require reviews and green checks before merging, add a rule under **Settings → Branch protection**. See [Pull requests](https://git.pkgforge.dev/docs/collaboration/pull-requests) and [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection). To skip the merge click from now on, open **Settings → Merge on green** once its checks have run: tick the checks and **Turn on auto-merge for pull requests I open**, and pull requests, yours and your agents', merge by themselves when the checks pass. See [Merge on green automatically](https://git.pkgforge.dev/docs/collaboration/merge-on-green). ## 8. Publish a release A release turns a tag into a version people can download, with release notes and attached files. **Web UI.** Open `https://git.pkgforge.dev/acme/website/releases` (or **Releases** in the sidebar of the repository page) and click **Draft a new release**. Under **Tag**, type a new tag such as `v0.1.0` (its **Target for a new tag** defaults to `main`), add a **Release title** and **Release notes**, optionally check **Generate release notes from merged pull requests (when the notes are empty)** and choose files under **Attach files**, then click **Publish release**. The release page also links to **Source code (zip)** and **Source code (tar.gz)** archives of the tag. **REST API** (GitHub-compatible, so Octokit and similar tools work too): ```sh curl -X POST https://git.pkgforge.dev/api/v3/repos/acme/website/releases \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{"tag_name": "v0.1.0", "name": "First release", "generate_release_notes": true}' ``` Publishing creates the tag if it doesn't exist. See [Releases](https://git.pkgforge.dev/docs/collaboration/releases). To deploy from a workflow with its own secrets and branch rules, use an environment (`environment: production` on a job); see [Environments](https://git.pkgforge.dev/docs/actions/environments). ## 9. Connect an AI agent over MCP Agents are separate accounts for AI tools. They act on behalf of the person or organization that owns them, never get more access than their owner, can't push or merge to the default branch or protected branches, and their pull requests always need a human approval. ### Create the agent **Web UI.** Go to **Settings → Agents**. Under **Create an agent**, enter the **Agent username** `review-bot`, a **Display name**, the **Owner** (you or `acme`) and the **Maximum role** (keep **Write**). Click **Create agent**. Then open **Create a token for review-bot**, keep the defaults (**Scope** **Write**, 30 **Days**) and click **Create token**. Copy the token; it is shown once. Tokens can't create agents or tokens, so create agents in the web UI under **Settings → Agents**, then create the agent's token in its row (**Create a token for**). The token is shown once. An agent owned by `acme` can work in every `acme` repository, up to its maximum role. Creating an organization agent needs the owner or admin role in the organization. ### Point your MCP client at Githome Githome's MCP server is at `https://git.pkgforge.dev/mcp` (Streamable HTTP). Give the client the agent's token as a bearer token: ```json { "mcpServers": { "githome": { "type": "http", "url": "https://git.pkgforge.dev/mcp", "headers": { "Authorization": "Bearer ghome_..." } } } } ``` `githome mcp-config` prints this snippet with `${GITHOME_TOKEN}` in place of the token, which clients such as Claude Code expand from the environment. For Claude Code, save it as `.mcp.json` in your project and set `GITHOME_TOKEN` to the agent's token. Or sign in with OAuth: `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp` for Claude Code, and `codex mcp add githome --url https://git.pkgforge.dev/mcp` for Codex (add `--bearer-token-env-var GITHOME_TOKEN` to use a token). Ask the agent something like "Use the githome tools: who am I, and what pull requests are open in acme/website?". It calls `whoami` and `list_pull_requests`. Agents can read and commit files without Git (`get_file`, `list_tree`, `commit_files`), open pull requests with an intent (`create_pull_request`), review, publish releases (`create_release`, `upload_release_asset`) and more. The tools that start work (a dispatch, a re-run, `sandbox_create`) are refused with "CI is off on this deployment" while the forge CI is dormant; the tools that read runs and logs (`list_workflow_runs`, `get_workflow_run`, `get_job_logs`) answer from stored data. See [MCP](https://git.pkgforge.dev/docs/agents/mcp) and the [MCP tool reference](https://git.pkgforge.dev/docs/reference/mcp-tools). ## Next steps - [Concepts](https://git.pkgforge.dev/docs/concepts): accounts, roles, tokens, visibility, Actions and agents in one page. - [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github): import a repository from GitLab, Forgejo, Gitea or Codeberg on the server, or from GitHub with a local import, then set its secrets again. - [Merge on green automatically](https://git.pkgforge.dev/docs/collaboration/merge-on-green): pull requests merge by themselves once their checks pass. - [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection): require pull requests, reviews and checks, and [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses) to report results from other CI systems. - [Releases](https://git.pkgforge.dev/docs/collaboration/releases) and [Environments](https://git.pkgforge.dev/docs/actions/environments): ship versions and deploy them. - [Organizations](https://git.pkgforge.dev/docs/accounts/organizations) and [Invitations](https://git.pkgforge.dev/docs/accounts/invitations): bring your team. - [Secrets and variables](https://git.pkgforge.dev/docs/actions/secrets-and-variables): give workflows credentials. - [Workflow syntax](https://git.pkgforge.dev/docs/actions/workflow-syntax) and [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). - [Agents](https://git.pkgforge.dev/docs/agents/overview) and [Sandboxes](https://git.pkgforge.dev/docs/agents/sandboxes): put AI agents to work safely. - [REST API](https://git.pkgforge.dev/docs/reference/rest-api) and the [CLI reference](https://git.pkgforge.dev/docs/reference/cli). --- # Concepts > The Githome mental model in one page: accounts, agents, repositories, roles, tokens, checks, releases, environments, Actions and audit. Source: https://git.pkgforge.dev/docs/concepts This page explains the building blocks of Githome and how they fit together. Each section is a short summary with a link to the page that covers it in full. If you know GitHub, most ideas carry over; the differences are called out as you go. All of it happens on githome, the private forge at `https://git.pkgforge.dev`, where accounts are made by invitation. The examples use that address. ## Accounts Every action on Githome is taken by an account. There are three kinds: users, organizations and agents. All three share one namespace, so `https://git.pkgforge.dev/diffy`, `https://git.pkgforge.dev/acme` and `https://git.pkgforge.dev/review-bot` are all account pages, and repositories live under users and organizations. ### Users A user is a person. Githome is invite-only, and [open sign-up](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in#open-sign-up) is off: you join by opening an invite link that the superadmin sends you, choosing a username and creating a passkey. There are no passwords. In the browser you sign in with a passkey; everything outside the browser (Git, the CLI, the REST API, MCP clients) uses a [token](#tokens). The superadmin administers githome in the dash at `https://dash.git.pkgforge.dev`: people and invitations, email, the audit log and more. The core has no **Site administration** section in settings. See [Passkeys and sign-in](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in), [Invitations](https://git.pkgforge.dev/docs/accounts/invitations) and [Site administration](https://git.pkgforge.dev/docs/admin/site-administration). ### Organizations An organization is a shared account that owns repositories, agents, container images and Actions secrets for a group of people. Members have one of three roles, which decide their role on every repository the organization owns: | Organization role | Role on the organization's repositories | | --- | --- | | member | The organization's base permission: `none`, `read`, `write` or `admin` | | admin | admin | | owner | admin, plus managing owners and renaming the organization | The base permission is a setting of the organization, as on GitHub: new organizations start with `read`, and owners change it on the organization's **Settings** tab. A member who creates a repository in the organization gets `admin` on it. Unlike GitHub, there are no teams and no custom roles. To give someone more access to a single repository, add them as a collaborator on it. See [Organizations](https://git.pkgforge.dev/docs/accounts/organizations) and [Base permission](https://git.pkgforge.dev/docs/accounts/organizations#base-permission). ### Agents An agent is an account for an AI tool or an automation, such as `review-bot`. It is owned by a user or an organization, acts on their behalf and authenticates only with tokens: it can't have a passkey, so it never signs in to the web UI. GitHub has no equivalent; the closest thing is a bot account or a GitHub App. Agents are held to guardrails that keep a person in the loop: - An agent never has more access than its owner. An organization's agent can reach only that organization's repositories. - Its maximum role is `write` unless its owner chooses otherwise. - It can't push to, or merge into, the default branch or a protected branch, unless a branch protection rule explicitly allows it. A rule can instead let it turn on auto-merge, so Githome merges its pull request once the required checks pass and a person approves (or, if an admin waives that, on green checks alone). - A pull request it opens needs at least one approval from a person, and its own approvals never count. - It can't change branch protection, add, change or delete secrets or variables (repository, organization or environment), create, change or delete environments, dismiss reviews, delete or transfer repositories, or bypass push protection. - Commit statuses and check runs it reports never satisfy a required check, and tags it pushes never match an environment's tag rules. - Commits it makes carry a `githome-agent` header naming the agent and the person it acts for. - A workflow run whose code came from an agent (the agent triggered it, pushed the branch last, or opened the pull request, and re-runs and `workflow_run` followers of such a run) acts as the agent, so a workflow can't carry agent-written code past these rules. - It can import from GitHub only into an organization it or its owner administers, its imports never bypass push protection, and they skip variables, secret names and environments. Agents work through the [MCP server](https://git.pkgforge.dev/docs/agents/mcp), the REST API, the CLI and Git. Githome can also run one for you, where the forge CI is on (it is dormant on git.pkgforge.dev, so no agent task, terminal or sandbox starts there now): an [agent task](https://git.pkgforge.dev/docs/agents/tasks) gives one of your agents a goal and runs Claude Code, Codex or your own command with your own model key, then opens a pull request, a [terminal](https://git.pkgforge.dev/docs/agents/terminal) gives you a shell in a sandbox where Claude Code or Codex runs on your own subscription and can take tasks too, a repository's [project](https://git.pkgforge.dev/docs/agents/projects) puts its tasks on a board with shared memory and instructions, and [agent review](https://git.pkgforge.dev/docs/agents/review) has one review pull requests for bugs. [Today](https://git.pkgforge.dev/docs/agents/today), the first page after signing in, shows what needs you and what your agents are doing. See [Agents](https://git.pkgforge.dev/docs/agents/overview). ### People imported from GitHub When you [import from GitHub](https://git.pkgforge.dev/docs/migrate-from-github), no accounts are created. A GitHub user whose GitHub account is linked to a Githome account (under **Settings → Linked accounts**, matched by GitHub's numeric user id) is credited to that account. Everyone else becomes a **mannequin**: a placeholder that carries their issues, comments and reviews under their GitHub login, with a **GitHub** badge in the web UI and `"type": "Mannequin"` and a `github:` login in the API. A mannequin isn't an account: it can't sign in or act. Imported reviews, whoever wrote them, are history and never count as approvals. See [People: linked accounts and mannequins](https://git.pkgforge.dev/docs/migrate-from-github#people-linked-accounts-and-mannequins). ## Repositories A repository holds a project's Git history plus its issues, pull requests, reviews, checks, releases, deployment environments, workflow runs, webhooks, secrets and variables. It lives at `https://git.pkgforge.dev//` (for example `https://git.pkgforge.dev/acme/website`) and is cloned from the same URL with `.git` appended. New repositories use `main` as the default branch unless you choose otherwise. A repository made on the web or with `githome repo create` is private unless you choose otherwise, and one made with the REST API is public unless the request asks for private, as on GitHub. A repository can be renamed, or transferred to your own account or to an organization you own or administer. Its old URLs keep working, as on GitHub: web pages and the REST API redirect, and Git, MCP and container images are served under the old name, for anyone who can still read it. To move from GitHub, the server-side importer copies a repository, or every repository of an organization, with its history, issues and pull requests (keeping their numbers), comments, reviews, labels, milestones, releases, branch protection, variables and environments. Secret values are never copied, only their names. Start it from **Settings → Imports**, `githome migrate github`, the REST API or MCP. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). A person who can read a repository can fork it (`gh repo fork`): the fork holds its own copy of the objects, and `gh repo sync` brings its branches up to their upstream. A pull request is between two branches of a repository, or from a branch of a fork: someone who can only read a repository forks it, pushes a branch to the fork and opens the pull request. Repositories can carry topics, and any branch, tag or commit can be downloaded as a `.zip` or `.tar.gz` source archive. Code is shown with syntax highlighting. See [Repositories](https://git.pkgforge.dev/docs/repositories/overview), [Browsing code](https://git.pkgforge.dev/docs/repositories/browsing-code), [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git) and [Git LFS](https://git.pkgforge.dev/docs/repositories/git-lfs). ## Visibility A repository is either **private** or **public**. | Visibility | Who can see it | | --- | --- | | Private | The owner, organization members (for organization repositories, unless the organization's base permission is `none`) and collaborators | | Public | Everyone, including people who aren't signed in. Signed-in users get `read`. | Someone without access to a private repository gets `404 repository not found`, never `403`, so its name isn't revealed. Writing to a public repository still needs a signed-in account (or a token) with a role that allows it. People who aren't signed in can only read: opening an issue, commenting, reacting or pushing without an account fails with `401 authentication required` (for a push, Git then asks for your token). See [Visibility](https://git.pkgforge.dev/docs/repositories/overview#visibility). ## Roles Every request to a repository runs with one effective role. Githome uses GitHub's five repository roles, and each one includes the ones before it: | Role | In short | | --- | --- | | `read` | View and clone; when signed in, also open issues and comment | | `triage` | Manage issues, pull requests and labels without pushing code | | `write` | Push, open and merge pull requests, run workflows | | `maintain` | Also move or delete tags, edit other people's comments and dismiss reviews | | `admin` | Settings, access, branch protection, secrets and webhooks | Your role on a repository comes from owning it, your organization role (members get the organization's base permission), a collaborator grant or the repository being public, whichever is highest. Tokens and agent limits can then only lower it. See [Permissions](https://git.pkgforge.dev/docs/accounts/permissions). ## Tokens A personal access token lets Git, the `githome` CLI, scripts and MCP clients act as you (or as an agent). Tokens start with `ghome_`, are shown once when you create them, and last 1 to 366 days (90 by default). Where the deployment sends email, Githome emails you whenever a token is created on your account. Each token has a scope that caps your role, whatever your role actually is: | Scope | Highest effective role | | --- | --- | | `read` | read | | `write` | maintain | | `admin` | admin | A `read` token can only read: it can clone and fetch, download Git LFS files, call `GET` endpoints and use the MCP tools that only read, and every change it attempts fails with `403 this token needs the write scope`. New tokens get the `write` scope unless you choose another; scopes other than `read`, `write` and `admin` are refused (`422`). Some actions belong to your account rather than to a repository, and need a minimum scope whatever your role: | Action | Token scope needed | | --- | --- | | Create a repository | `write` | | Create an organization, send invitations, manage organization secrets | `admin` | | Create or revoke tokens, create or disable agents, create agent tokens | `admin` | A token can also be restricted to a list of repositories; every other repository then answers `404` as if you had no access, and the token can't create repositories or organizations, send invitations, manage agents or create other tokens. A token can only be restricted to repositories your account can see. Browser sessions aren't capped, so in the web UI you always act with your full role. Unlike GitHub's fine-grained tokens, there are no per-permission settings: the scope and the repository list are the whole model. Use a token as the Git password (with any username), as `Authorization: Bearer ghome_...` for the API and MCP, or let `githome login` and `githome auth setup-git` store it. See [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens). ## Job tokens > The forge CI of git.pkgforge.dev is dormant: no Actions run, hosted job, agent sandbox, task or terminal starts there now. The sections on job tokens, Actions, runners, environments and sandboxes describe the code that stays in githome. Each workflow job gets a short-lived job token as `GITHUB_TOKEN` (also `GITHOME_TOKEN`). It starts with `ghomejt_`, acts as `githome-actions[bot]` on the repository the job runs in (it can also read other public repositories) and stops working when the job completes. As on GitHub, the token can do what the workflow's `permissions:` grant (`contents`, `issues`, `pull-requests`, `statuses`, `packages` and so on), and an endpoint it lacks the permission for answers `403 Resource not accessible by integration`. Without `permissions:`, a job gets the repository's default, which for new repositories is GitHub's restricted one (`contents` and `packages` read); a repository admin can change it (see [Workflow permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions)). The token never acts above `write`, so branch protection applies; it never changes repository settings, secrets or workflow files; it can't open or approve pull requests unless the repository allows it, and its approvals never count; and a run whose code came from an agent acts as that agent. Sandboxes get a similar token starting with `ghomest_` (see [Sandboxes](#sandboxes)). See [Job tokens and sandbox tokens](https://git.pkgforge.dev/docs/accounts/permissions#job-tokens-and-sandbox-tokens) and [Secrets and variables](https://git.pkgforge.dev/docs/actions/secrets-and-variables). ## Branch protection A branch protection rule matches branch names with a pattern such as `main`, `release/*` (one path segment) or `release/**` (any depth), and controls how matching branches can change: whether changes must go through a pull request, how many approvals and which checks are required, whether force pushes, deletion and merge commits are allowed, whether a merge queue is used, and what agents may do. The server enforces the rules for every way a branch can change, whether through `git push`, the REST API, MCP or the web UI. Required checks can be workflow jobs, check runs or commit statuses reported by other tools. When Githome Actions reports a check, it alone decides that check; to have another tool decide a required check, a rule binds the check to that reporter. See [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). Some protections apply even without any rule: the default branch can't be deleted, and agents can't push to it or merge into it. When several rules match a branch, the rule that names the branch exactly wins over patterns; otherwise the oldest matching rule applies. Repository admins can bypass the rules unless the rule sets **Do not allow administrators to bypass these rules** (`enforceAdmins`). A push by an admin bypasses them on its own. A merge doesn't: an admin has to ask for it explicitly (the **Merge without waiting for requirements (bypass)** button, `"bypass_rules": true` in the API, or `githome pr merge --admin`), and the bypass is recorded in the audit log as `pull_request.merge_bypassed`. `"bypass_rules": true` skips unmet rules, and `"bypass_merge_queue": true` skips only a required merge queue. Bypassing merge requirements is for people only, never agents, and never works for a draft or a pull request with conflicts. See [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection) and [Merge queue](https://git.pkgforge.dev/docs/collaboration/merge-queue). ## Pull requests with intent A pull request proposes merging one branch (the head) into another (the base) of the same repository. Pull requests and issues share one number sequence per repository, as on GitHub. Besides a title and a description, every pull request can carry an **intent**: one or two sentences on what the change is meant to achieve, for example "Fix the race in token refresh without changing the public API." The intent is shown at the top of the pull request, included in notification emails and returned by the API, the CLI and MCP, so reviewers, human or AI, can check the diff against the stated goal. It can't be edited after the pull request is opened, and agents should always set it. A pull request can be opened as a **draft**: a draft can't be merged until it is marked ready for review (the **Ready for review** button, `githome pr ready`, or `PATCH` with `"draft": false`), and it can be turned back into a draft later. Pull requests are reviewed with **Approve**, **Request changes** or comments, checked by workflow runs and other CI, and merged with a merge commit, a squash or a fast-forward rebase once nothing blocks them. With **auto-merge** turned on, Githome merges a pull request by itself as soon as nothing blocks it. See [Pull requests](https://git.pkgforge.dev/docs/collaboration/pull-requests) and [Issues](https://git.pkgforge.dev/docs/collaboration/issues). ## Actions Githome Actions runs GitHub Actions workflows from `.githome/workflows/`, or from `.github/workflows/` when a repository has no `.githome/workflows/`, on Cloudflare. On git.pkgforge.dev it is dormant, so no workflow runs there now. Most existing workflow files run unchanged; differences are listed in [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). ### Runs, jobs and steps | Term | Meaning | | --- | --- | | Workflow | A YAML file that says when to run (`on:`) and what to run (`jobs:`). | | Event | What starts a workflow: a push, a pull request update, a merge queue group, a manual dispatch, a schedule, another workflow's run, a published release or a `repository_dispatch` API call. | | Run | One execution of one workflow for one event, with a number, a status and a conclusion. | | Job | A set of steps that runs on one runner. Jobs run in parallel unless linked with `needs`; a matrix expands one job into several. | | Step | One command (`run:`) or one action (`uses:`), run in order in the job's workspace. | | Check | The result of one job, reported on the commit as ` / `, for example `CI / test`. Branch protection can require it. | | Environment | A deployment target such as `production`, with its own secrets, variables and branch policy. A job with `environment:` gets them only if the policy allows the ref. | Runs are orchestrated durably, so they survive platform restarts, and a job can run for at most 6 hours. See [Actions overview](https://git.pkgforge.dev/docs/actions/overview), [Workflow syntax](https://git.pkgforge.dev/docs/actions/workflow-syntax) and [Events that trigger workflows](https://git.pkgforge.dev/docs/actions/events). ### Runners A runner is the machine that executes one job. You pick one per job with `runs-on`: - **Hosted runners** would run each job in a fresh container on Cloudflare, with `runs-on: ubuntu-latest` and similar labels. They are dormant on git.pkgforge.dev. - **Self-hosted runners** run jobs on a machine you control, such as a Mac, a GPU box or a server on a private network. You start one with `githome runner`, and jobs with `runs-on: self-hosted` (plus any other labels) go to it. See [Runners](https://git.pkgforge.dev/docs/actions/runners). ## Checks and commit statuses A check is a pass or fail result attached to a commit. Githome Actions reports one check per job. Other tools report results over the GitHub-compatible REST API, either as **commit statuses** (a state and a context name, such as `ci/external`) or as **check runs**. All of them appear together on the commit and the pull request, and branch protection can require any of them by name. See [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). ## Releases A release marks a tag as a version you ship, with a title, Markdown release notes and downloadable files (assets, up to 100 MB each). Releases can be drafts or pre-releases, one of them is the latest, and notes can be generated from the merged pull requests. Each release page also links to source archives of its tag. Publishing a release starts `on: release` workflows and sends a `release` webhook. Manage releases at `https://git.pkgforge.dev/acme/website/releases`, with the REST API or with the MCP release tools. See [Releases](https://git.pkgforge.dev/docs/collaboration/releases). ## Environments and deployments An environment, such as `staging` or `production`, groups the secrets and variables a deployment needs with a policy for which branches and tags may deploy to it. A workflow job that names an environment (`environment: production`) creates a deployment, gets that environment's secrets and variables, and is refused if the policy doesn't allow its ref. Environment secrets never reach pull request runs. Tools outside Actions can record deployments and their status through the REST API, as on GitHub. Environments are managed with the REST API by repository admins. See [Environments](https://git.pkgforge.dev/docs/actions/environments). ## Sandboxes A sandbox is a short-lived Linux container with a repository already cloned into it, which you drive over MCP or the REST API: run shell commands, read and write files, and push with Git. Agents use sandboxes to build and test changes without a machine of their own. Creating one is refused on git.pkgforge.dev with "CI is off on this deployment". Creating a sandbox needs write access. Inside it, Git authenticates as whoever created it with at most `write`, so branch protection, push protection and agent guardrails apply to its pushes like any other. A sandbox stops after 30 minutes without calls and keeps no files, so commit and push what you want to keep. GitHub has no built-in equivalent. See [Sandboxes](https://git.pkgforge.dev/docs/agents/sandboxes). ## Push protection Every `git push` is scanned for leaked credentials such as API keys and private keys, and so is every commit made without Git: in the web editor, through the REST API (`POST /repos/{owner}/{repo}/githome/commits` and the contents and git data APIs) and with the MCP `commit_files` tool. A push or commit that contains one is rejected and nothing from it is stored. A repository admin who is a person can push anyway with `git push -o allow-secrets=`, or commit through the commits API with `allow_secrets`, which is recorded in the audit log. See [Push protection](https://git.pkgforge.dev/docs/security/push-protection) and [Security overview](https://git.pkgforge.dev/docs/security/overview). ## Audit log The audit log is an append-only record of security-relevant actions: sign-ins, passkey and token changes, repository settings (whether changed on the web or through the API), pushes, force pushes, merges, push protection decisions and package changes. When an agent acts, the entry names both the agent and the account it acts for. Only the superadmin can view it, on the page **Audit log** of the dash, which shows the 200 most recent entries. See [Audit log](https://git.pkgforge.dev/docs/security/audit-log). ## Notifications Githome tells you about activity in the notifications list (the bell in the header, `/notifications`) and by email, following GitHub's rules: you hear about issues and pull requests you take part in, everything in repositories you watch with **All activity**, and failed workflow runs you started. Security emails, such as a new token or a new sign-in, are always sent. Each repository has a **Watch** menu (**Participating and @mentions**, **All activity**, **Ignore**), each issue and pull request a **Subscribe** button, and **Settings → Notifications** turns each group on or off. Agents have no notification settings. See [Notifications](https://git.pkgforge.dev/docs/accounts/notifications). ## Where to go next - [Quickstart](https://git.pkgforge.dev/docs/quickstart): try these concepts end to end in about 15 minutes. - [Releases](https://git.pkgforge.dev/docs/collaboration/releases), [Environments](https://git.pkgforge.dev/docs/actions/environments) and [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). - [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github): import repositories or whole organizations, link your GitHub account, and set secrets again. - [REST API](https://git.pkgforge.dev/docs/reference/rest-api), the [CLI reference](https://git.pkgforge.dev/docs/reference/cli) and the [MCP tool reference](https://git.pkgforge.dev/docs/reference/mcp-tools). - [Limits](https://git.pkgforge.dev/docs/reference/limits): sizes, timeouts and quotas in one place. --- # Migrate from GitHub > Import GitHub repositories or whole organizations with the server-side importer (web, CLI, API or MCP), then set secrets, update remotes and check workflows. Source: https://git.pkgforge.dev/docs/migrate-from-github Githome imports a GitHub repository, or every repository of a GitHub organization or user, on the server: it copies the Git history and everything else through GitHub's REST API, keeping issue and pull request numbers, comments, reviews and their authors. You start an import from the web, the `githome` CLI, the REST API or MCP, and nothing runs on your machine. **On git.pkgforge.dev the server-side import from GitHub does not complete:** its Git step needs the import container, which the deployment does not run while the forge CI is dormant, so the import stops at its Git step with "no import container is configured". A GitHub repository comes in through [the local client-side import](#the-local-client-side-import) or a GitHub pull mirror (the **Mirrors** page of the dash). Imports from GitLab, Forgejo, Gitea and Codeberg run on the server without a container. This page covers the importer in full, the older client-side and plain Git paths, mirroring from GitHub, and what to change after you move. The importer reads GitLab, Forgejo, Gitea and Codeberg too: see [Import from GitLab, Forgejo or Gitea](#import-from-gitlab-forgejo-or-gitea). ## Choose a method | Method | Copies | Use it when | | --- | --- | --- | | [The server-side importer](#how-the-importer-works) (web, `githome migrate github`, REST API, MCP) | Branches, tags, pull request heads, Git LFS objects, issues and pull requests with their numbers, comments, reviews and review comments, labels, milestones, releases and assets, branch protection, Actions variables, deployment environments with their variables, and the names (never the values) of secrets. | You are moving a repository or an organization to Githome. This is the default. | | [`githome migrate github --local`](#the-local-client-side-import) | Branches, tags, default branch, repository variables and secret names. With `--issues`, also labels, issues, comments and open pull requests, created anew. | You want the older client-side path that clones on your machine. | | [Plain Git](#move-with-plain-git) | Branches and tags. | You only need the code. | | [Mirror from GitHub](#keep-github-as-upstream-and-mirror-to-githome) | Every branch and tag on every push, plus the secrets you list. | You want a copy on Githome while your team keeps working on GitHub. | Whatever you choose, your `.github/workflows/*.yml` files come across as files, but the forge CI of git.pkgforge.dev is dormant, so no workflow runs there now. See [Workflows](#workflows). ## How the importer works An import is a record on the server that runs through fixed steps, each retried on failure and resumed where it stopped: 1. **Create the repository** under the Githome user or organization you chose, with GitHub's description, homepage, topics (up to 20) and default branch. 2. **Copy branches, tags and history.** The importer clones the GitHub repository with `git clone --mirror` and pushes it to Githome in chunks, then copies Git LFS objects. This step needs the import container; on git.pkgforge.dev, which does not run one, a GitHub import stops here with "no import container is configured". 3. **Copy issues, pull requests, comments, reviews, review comments, labels, milestones, branch protection, variables, secret names, environments and releases** through GitHub's REST API, page by page. 4. **Finish:** create `refs/pull//head` for every imported pull request, set the default branch, archive the repository if it is archived on GitHub, and write the summary. Things to know: - **Nothing the import writes fires events.** No webhooks are delivered and nobody is notified about imported issues, comments or pushes. - **The repository is locked while the import runs.** Until the import finishes, fails or is cancelled, only the import writes to it. A push from anyone else is refused with `repository is locked by an import in progress`, and any other change through the REST API, the web UI or MCP (an issue, a comment, a label, a webhook, a branch protection rule, a rename or transfer) gets `423 repository is locked by an import in progress; try again when it finishes, or cancel the import`. Reading the repository and watching it work as usual, and so do settings that don't touch its Git data, issues or pull requests: Actions secrets and variables, environments with their secrets and variables, and collaborators and their invitations. You can set the imported secrets' values while the history is still arriving. - **Every write is keyed by GitHub's ids**, so a retried step or a retried import never duplicates issues, pull requests, comments, reviews, labels, milestones, branch protection rules or releases (a release is matched by its tag and creation date, and assets already copied are kept). - **The import keeps running if you close the page or stop the CLI.** You get an entry in your notifications list when it succeeds (`Imported acme/website into acme/website`) or fails, linking to its page. - **Every import is audited:** `import.create`, `import.push`, `import.finish`, `import.fail`, `import.cancel` and `import.retry` appear in the audit log. See [Audit log](https://git.pkgforge.dev/docs/security/audit-log). ## Before you start You need: - **A Githome account.** Githome is invite-only, and [open sign-up](https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in#open-sign-up) is off. Ask the superadmin for an invitation link, which the superadmin sends by hand: githome sends no email for it. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations). - **An organization** if the repositories should belong to one, for example `acme`, where you are an owner or admin. Create it under **Settings → Organizations**. See [Organizations](https://git.pkgforge.dev/docs/accounts/organizations). - **For the CLI, API or MCP, a Githome token with the `write` or `admin` scope.** Use `admin` if old history may contain credentials and you want them imported with a bypass (see [Secrets in old history](#secrets-in-old-history)). The web UI needs no token. See [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens). - **A GitHub token** for a private repository, and for Git LFS, variables, secret names, environments and branch protection. See [GitHub token](#github-token). - **Optionally, a linked GitHub account**, so your own past issues, comments and reviews are attributed to your Githome account. Link it before you import. See [Link your GitHub account](#link-your-github-account). ### Who can import where | Who | Can import into | | --- | --- | | A person | Their own account, and organizations where they are an owner or admin | | An agent | Only organizations: the organization that owns the agent, or one where the agent's owner is an owner or admin. Never a user account. The agent's maximum role must be at least `write`. | | An organization | Nothing: `organizations cannot start imports` | Organization members who aren't owners or admins can't import into the organization (`you can import only into your own account or organizations you administer, not acme`). The check runs again when the import starts; if you lost the right in the meantime the import fails with `the person or agent who started this import can no longer import into this account`. ### GitHub token Without a GitHub token, the importer reads only public data, and GitHub's limit for anonymous requests (60 an hour) makes a large import slow. The importer waits whenever GitHub asks it to, so it still finishes. With a token: | To import | The GitHub token needs | | --- | --- | | A private repository, its Git data, issues, pull requests, comments, reviews, labels, milestones and releases | Classic token: the `repo` scope. Fine-grained token: read access to **Contents**, **Metadata**, **Issues** and **Pull requests**. | | Branch protection | Admin access to the repository on GitHub | | Actions variables, secret names and environments | Admin access to the repository, or for a fine-grained token **Variables** and **Secrets** read access | | Organization variables and secret names (organization imports) | Admin access to the GitHub organization | | Private repositories of a GitHub organization or user (organization imports) | Access to those repositories; the list includes private ones only when the token can see them | When the token can't read something optional, the import carries on and records a warning, for example `Branch protection of main could not be read (the GitHub token needs admin access to the repository); set it up under Settings → Branch protection.` How the token is handled: - It is used only for this import, encrypted at rest, and deleted when the import finishes, fails or is cancelled. A retry needs it again. - It is never returned by the API, MCP or the web UI, and never written to logs. Git gets it from per-host configuration, never on its command line. - It is sent only to the one GitHub host you import from. Redirects to another host are not followed, the clone URL must be on that host (`GitHub returned a clone URL on another host`), and release assets get the token only when they are on the API's own origin. - The CLI sends `GH_TOKEN` (or `GITHUB_TOKEN`) to Githome over HTTPS so the server can use it, and says so on stderr (`note: sending GH_TOKEN to https://git.pkgforge.dev so it can read from GitHub during the import`). Unset both to import only public data without a token. ### GitHub Enterprise Server To import from GitHub Enterprise Server, name its REST API base explicitly: the **GitHub Enterprise API URL** field in the web form, `github_api_url` in the API and MCP, or `GITHUB_API_URL` for the CLI. The rules: | Rule | Details | | --- | --- | | Default | `https://api.github.com`. `github.com`, `www.github.com` and `api.github.com` all mean github.com. | | Form | `https://ghe.example.com/api/v3`. A bare host such as `https://ghe.example.com` gets `/api/v3` added. | | Must be https on a public host | Otherwise `github_api_url must use https`, `github_api_url must be a public host` (localhost, single-label names, `.local`, `.internal` and private or loopback addresses are refused), `github_api_url must not contain credentials` or `github_api_url is not a valid URL`. | | A token with an Enterprise source URL | If `source` is a URL on an Enterprise host and you give a token, `github_api_url` is required (`github_api_url is required when a github_token is given and the source names a GitHub Enterprise host`) and must be on the same host (`github_api_url must be on the same host as the source repository`). This keeps a token from going to a host taken from the source URL. | | No token | A source URL on an Enterprise host implies `https:///api/v3`. | Release assets are downloaded only from github.com's asset hosts and from the GitHub Enterprise host the deployment configured (`IMPORT_GHE_HOST`). On other Enterprise hosts, assets are skipped with a warning and the releases themselves are still imported. ## Import from the web ### One repository 1. Open the import form in any of these ways: - **Settings → Imports**, then **Import from GitHub**. - On **Create a new repository** (`https://git.pkgforge.dev/new`), the **Import a repository** link. - On an organization's page, **Import from GitHub** next to **New repository** (shown to its owners and admins; it opens the form for an organization import into that organization). - Directly: `https://git.pkgforge.dev/new/import`. 2. Under **What to import**, choose **One repository**. 3. In **Repository, or organization, group or user**, enter `acme/website` or `https://github.com/acme/website`. 4. In **Import into**, choose yourself or an organization you administer. 5. Optionally set **New repository name** (defaults to the GitHub name). 6. Choose **Visibility**: **Keep** (a public GitHub repository stays public, any other becomes private), **Private** or **Public**. 7. Paste a **Token** if the repository is private or you want LFS, variables and protection. 8. Optionally open **What to copy, and GitHub Enterprise** to turn parts off, choose what happens to [secrets in old history](#secrets-in-old-history), or set **GitHub Enterprise API URL**. See [Import options](#import-options). 9. Click **Start import**. The import's page opens and follows its progress. ### An organization or user 1. Open the import form as above. The **Import from GitHub** button on an organization's page preselects it. 2. Under **What to import**, choose **A whole organization or user**. 3. In **Repository, or organization, group or user**, enter the GitHub organization or user, for example `acme`. 4. Choose **Import into**, **Visibility**, the **Token** and the options, and set **Repositories at a time** (1 to 8, default 3). 5. Click **Start import**. The **Choose repositories** page lists the account's repositories with `private`, `fork` and `archived` badges. Everything except forks and archived repositories is ticked. 6. Use the filter box with **Filter**, **Select all** (or **Select all shown** when filtered) and **Clear** to adjust the selection, then click **Import N repositories**. Each repository becomes its own import under the organization import, keeps its GitHub name, and is imported in full. A repository whose name already exists in the target fails straight away with `acme/website already exists`; the others go ahead. An organization import waiting on **Choose repositories** is a draft. Drafts left for seven days are cancelled (`draft expired`) and their stored GitHub token is erased. ### Import options | Web label | API field (`options.`) | Default | What it controls | | --- | --- | --- | --- | | **Issues and pull requests** | `issues` | on | Issues and pull requests with comments, reviews and review comments | | **Labels and milestones** | `labels` | on | Labels and milestones, even without issues | | **Branch protection** | `branch_protection` | on | Classic branch protection rules | | **Actions variables and secret names** | `variables` | on | Repository variables, secret names, and deployment environments with their variables and secret names; for organization imports also organization variables and secret names | | **Releases** | `releases` | on | Releases and their assets | | **Git LFS objects** | `lfs` | on | Git LFS files | | **Secrets found in old history (push protection)**: **Import with an audited bypass** or **Stop the import** | `secrets`: `"bypass"` or `"stop"` | `bypass` | What happens when push protection finds a credential in old commits. Agents always get `stop`. | Branches, tags and history are always copied. A step whose option is off shows as skipped with `Not selected`. ### Follow progress The import's page (`https://git.pkgforge.dev/imports/`) refreshes itself every few seconds while the import runs ("This page refreshes automatically.") and shows: - The source, the target and a status badge: `queued`, `running`, `succeeded`, `failed` or `cancelled` (and `draft` for an organization import that waits for its selection). - Each step with its state and a short message, such as `12 branches, 30 tags, 118 pull request heads, 4 LFS objects`. - For an organization import, every repository with its status and an **Open** button. - After it finishes: **Imported** (counts), **Secret names** with a **Set secret values** button, **Possible secrets in history (rotate these)** when a bypass was used, and **Warnings**. - **Cancel import** while it runs, and **Retry this import** when it failed or was cancelled. **Settings → Imports** (`https://git.pkgforge.dev/imports`) lists the imports you started, newest first. Admins of the target account can also open an import's page by its link. | Step | Title on the page | | --- | --- | | `repository` | Create the repository | | `git` | Copy branches, tags and history | | `labels` | Labels and milestones | | `issues` | Issues and pull requests | | `comments` | Comments | | `reviews` | Reviews | | `review_comments` | Review comments | | `protection` | Branch protection | | `variables` | Variables and secret names | | `releases` | Releases | | `finalize` | Finish | An organization import has three steps: `organization` (**Organization variables and secret names**), `repositories` (**Repositories**, with `3 of 10 finished (2 imported, 1 failed)`) and `finalize` (**Finish**). Each step is `pending`, `running`, `done`, `skipped` or `failed`. ## Import with the CLI Install the CLI and sign in (approve the sign-in in your browser; `--scope admin` if you'll also set secrets): ```sh curl -fsSL https://git.pkgforge.dev/install | bash githome login # opens your browser to authorize ``` ### githome migrate github Starts a server-side import of one repository and follows it until it finishes: ```sh export GH_TOKEN=ghp_... # needed for private repositories, LFS, variables and protection githome migrate github acme/website --to acme/website ``` ```text githome migrate github [options] ``` The argument can also be a URL such as `https://github.com/acme/website`; the CLI keeps only `owner/name` from it, so for GitHub Enterprise set `GITHUB_API_URL`. | Option | Default | Meaning | | --- | --- | --- | | `-t, --to OWNER/NAME` | `/` | The Githome repository to create. It must not exist yet. | | `-p, --private` | off | Create the repository as private, whatever its visibility on GitHub (otherwise visibility is kept) | | `-l, --local` | off | Run the older client-side import instead. See [The local client-side import](#the-local-client-side-import). | | `-i, --issues` | off | With `--local` only: also copy labels, issues, comments and open pull requests | | `--json` | off | Print the final import object as JSON instead of progress lines | | Environment variable | Meaning | | --- | --- | | `GH_TOKEN` or `GITHUB_TOKEN` | GitHub token, sent to Githome for the import (`GH_TOKEN` wins if both are set) | | `GITHUB_API_URL` | GitHub Enterprise API base, for example `https://ghe.example.com/api/v3` | | `GITHOME_TOKEN`, `GITHOME_URL` | Override the token and server saved by `githome login` | The CLI imports with every option on and `secrets` set to `bypass`. To turn parts off or stop on secrets, use the web form or the API. While it runs, the command prints each step and Git phase as it changes: ```text Starting server import of acme/website … … Create the repository ✓ Create the repository (acme/website) … Copy branches, tags and history (Starting the Git transfer) … git: Cloning acme/website … git: Pushing history of main: chunk 1 (31.6 MB) ✓ Copy branches, tags and history (42) ✓ Labels and milestones (14) ✓ Issues and pull requests (220) ... ✓ Finish (180 issues, 40 pull requests) Imported acme/website → acme/website GitHub does not reveal secret values. Set these 3 secrets by hand: githome secret set NPM_TOKEN -R acme/website githome secret set SENTRY_DSN -R acme/website githome api PUT /repos/acme/website/environments/production/secrets/DEPLOY_KEY -f value=... https://git.pkgforge.dev/acme/website ``` Warnings are printed to standard error. Repository secrets get a `githome secret set` line. Environment secrets (`production/DEPLOY_KEY` in the summary) have no `secret set` option, so they get a `githome api PUT .../environments//secrets/` line instead (see [Environments and their secrets](#environments-and-their-secrets)). Replace `...` with the value, or pipe it in. Stopping the command (Ctrl-C) stops following, not the import. Check on it at `https://git.pkgforge.dev/imports` or with `GET /api/v3/githome/imports`. ### githome migrate github-org Starts a server-side import of many repositories of a GitHub organization or user and follows it until every repository has finished: ```sh export GH_TOKEN=ghp_... githome migrate github-org acme --to acme --exclude-forks --exclude-archived ``` ```text githome migrate github-org [options] ``` | Option | Default | Meaning | | --- | --- | --- | | `-t, --to OWNER` | you | The Githome user or organization to import into | | `--repos A,B,C` | all | Comma-separated names of the repositories to import | | `-p, --private` | off | Create every repository as private | | `--exclude-forks` | off | Skip forks | | `--exclude-archived` | off | Skip archived repositories | | `-c, --concurrency N` | 3 | Repositories imported at the same time, 1 to 8 | | `--json` | off | Print the final import object as JSON | Unlike the web form, the CLI has no selection step: it starts importing the repositories straight away. It prints a line per repository as its state changes, then a summary such as `Bulk import of acme: 9/10 repositories imported, 1 failed` and the import's URL. ### JSON output and exit status With `--json`, both commands print the final [import object](#the-import-object). Both exit with status `0` when the import succeeded and `1` otherwise (failed or cancelled). An organization import counts as failed when any of its repositories wasn't imported. ### The local client-side import `githome migrate github --local` runs the older import on your machine. It needs Git 2.31 or newer and a Githome token with the `admin` scope that isn't restricted to repositories, from a person, not an agent (it creates the repository, sets the default branch and Actions variables). Run `githome auth setup-git` once so Git can use the token. ```sh export GH_TOKEN=ghp_... githome migrate github acme/website --to acme/website --local --issues ``` What it does: 1. Creates the target repository with GitHub's description and visibility (or private with `--private`), or uses it if it exists (`Using existing repository acme/website`). 2. Clones with `git clone --mirror` into a temporary folder and pushes every `refs/heads/*` and `refs/tags/*` in one `git push`. If that fails, it prints `warning: bulk push failed (...); pushing refs one at a time` and pushes each ref separately. 3. Sets the default branch, copies repository variables and lists secret names with a `githome secret set` line for each. 4. With `--issues`: copies labels, then creates issues, recreates open pull requests whose branches are in the same repository, copies conversation comments and closes closed issues. Everything is created by you, now, with new numbers (the output lists `GitHub #12 → #9`), and each item starts with an attribution line such as `> Imported from GitHub issue [#12](https://github.com/acme/website/issues/12) by @diffy on 2026-03-01`. It doesn't copy closed or merged pull requests, reviews, review comments, milestones, assignees, releases, Git LFS files, environments or branch protection, and pushes go through push protection like any other push. `--issues` isn't idempotent: running it twice creates every issue again. It exits with status 1 if any branch or tag failed to push. With `--json` it prints `repo`, `created`, `branches`, `tags`, `pushFailures`, `defaultBranch`, `labels`, `issues` and `pulls` (`{from, to}` pairs), `skippedPulls`, `comments`, `variables`, `secrets` and `warnings`. Prefer the server-side import: it keeps numbers, authors, dates, reviews and merged pull requests, and doesn't depend on your connection. ## Import with the REST API The importer is a Githome extension of the REST API under `/api/v3/githome/imports`. Every endpoint needs a token (or a browser session). Starting an import needs the `write` or `admin` scope (`starting an import needs a token with write or admin scope`); cancelling, retrying and choosing repositories need the `write` scope on a token that isn't restricted to repositories. ### Start an import `POST /api/v3/githome/imports` with a JSON body. One repository: ```sh curl -X POST https://git.pkgforge.dev/api/v3/githome/imports \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{ "source": "acme/website", "owner": "acme", "name": "website", "visibility": "keep", "github_token": "ghp_...", "options": { "releases": true, "secrets": "bypass" } }' ``` Many repositories from an organization or user: ```sh curl -X POST https://git.pkgforge.dev/api/v3/githome/imports \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{ "source_owner": "acme", "owner": "acme", "exclude_forks": true, "exclude_archived": true, "concurrency": 4, "github_token": "ghp_..." }' ``` | Field | Applies to | Default | Meaning | | --- | --- | --- | --- | | `source` | One repository | | `owner/name`, a github.com or Enterprise URL, or an SSH remote such as `git@github.com:acme/website.git`. Give either `source` or `source_owner`. | | `source_owner` | Many | | A GitHub organization or user login | | `owner` | Both | required | The Githome user or organization to import into | | `name` | One repository | the GitHub name | The new repository's name: letters, digits, `.`, `-` and `_`. It must not exist yet. | | `repositories` | Many | all | Names of the repositories to import, at most 1,000. Unknown names fail the request (`not found in acme: a, b`). | | `exclude_forks` | Many | `false` | Skip forks (ignored when `repositories` is given) | | `exclude_archived` | Many | `false` | Skip archived repositories (ignored when `repositories` is given) | | `concurrency` | Many | `3` | Repositories imported at the same time, 1 to 8 | | `visibility` | Both | `keep` | `keep`, `private` or `public`. With `keep`, a public GitHub repository stays public and any other becomes private. | | `options` | Both | everything on, `secrets: "bypass"` | An object with `issues`, `labels`, `branch_protection`, `variables`, `releases`, `lfs` (booleans) and `secrets` (`"bypass"` or `"stop"`). Unknown keys fail with `unknown option "..."`. See [Import options](#import-options). | | `github_token` | Both | none | GitHub token; at most 400 characters, no spaces | | `github_api_url` | Both | `https://api.github.com` | GitHub Enterprise API base. See [GitHub Enterprise Server](#github-enterprise-server). | Before it records anything, the server reads the source on GitHub, so mistakes fail right away: `GitHub repository acme/website was not found or the token cannot read it`, `GitHub rejected the token (expired or revoked?)`, `no GitHub organization or user named acme`, `acme has no repositories to import`, or `acme/website already exists; choose another name`. A single repository larger than the size limit is refused here too (see [Limits](#limits)). The response is `201 Created` with the [import object](#the-import-object). An organization import created through the API starts at once with the repositories you named (or all of them); the draft and selection step exists only in the web form. ### The import object The same object is returned by the REST API, by the MCP tools and by `--json`. It never contains a credential. ```json { "id": "01JA7Q3V9X2M8K4T6R5N0B1C2D", "url": "https://git.pkgforge.dev/api/v3/githome/imports/01JA7Q3V9X2M8K4T6R5N0B1C2D", "html_url": "https://git.pkgforge.dev/imports/01JA7Q3V9X2M8K4T6R5N0B1C2D", "kind": "repository", "parent_id": null, "status": "running", "attempt": 1, "source": { "full_name": "acme/website", "html_url": "https://github.com/acme/website", "api_url": "https://api.github.com" }, "target": { "owner": "acme", "name": "website", "full_name": "acme/website", "html_url": "https://git.pkgforge.dev/acme/website" }, "visibility": "keep", "options": { "issues": true, "releases": true, "labels": true, "branch_protection": true, "variables": true, "lfs": true, "secrets": "bypass" }, "created_by": { "login": "diffy", "type": "User" }, "steps": [ { "name": "repository", "title": "Create the repository", "status": "done", "message": "acme/website", "count": null, "started_at": "2026-10-13T09:00:01.000Z", "finished_at": "2026-10-13T09:00:03.000Z" }, { "name": "git", "title": "Copy branches, tags and history", "status": "running", "message": "Starting the Git transfer", "count": null, "started_at": "2026-10-13T09:00:03.000Z", "finished_at": null } ], "git": { "phase": "push", "message": "Pushing history of main: chunk 3 (31.9 MB)", "chunks": 2, "bytes": 66846720, "tries": 1 }, "summary": {}, "warnings": [], "error": null, "created_at": "2026-10-13T09:00:00.000Z", "updated_at": "2026-10-13T09:04:12.000Z", "started_at": "2026-10-13T09:00:01.000Z", "finished_at": null } ``` | Field | Meaning | | --- | --- | | `kind` | `repository` or `organization` | | `parent_id` | For a repository of an organization import, the organization import's id | | `status` | `draft`, `queued`, `running`, `succeeded`, `failed` or `cancelled` | | `attempt` | 1, plus one per retry | | `target.html_url` | Set once the repository exists | | `steps` | Every step in order, with `status` (`pending`, `running`, `done`, `skipped`, `failed`), `message` and `count` | | `git` | The Git transfer: `phase` (`starting`, `clone`, `lfs-fetch`, `push`, `refs`, `lfs-push`, `cleanup`, `done` or `failed`), `message`, history `chunks` and `bytes` pushed, and `tries` | | `summary` | Filled in as steps finish: `counts` (`issues`, `pulls`, `comments`, `reviews`, `labels`, `milestones`), `git` (`branches`, `tags`, `pullRefs`, `lfsObjects`, `lfsBytes`, `defaultBranch` and more), `pullRefs.missing`, `protections`, `variables`, `secretNames`, `environments` (`imported`, `variables`, `secretNames`), `releases` (`imported`, `assets`, `skippedAssets`), `findings` (`kind`, `blob`, `path`), `people` (`linked`, `imported`), and for organization imports `orgVariables`, `orgSecretNames` and `children` counts | | `warnings` | Things that didn't come across, in words | | `error` | Why the import failed or who cancelled it | | `concurrency`, `candidates`, `children` | Organization imports only: the concurrency, the repositories to choose from (drafts), and each repository import (`id`, `html_url`, `source`, `target`, `status`, the running `step`, `error`) | ### Endpoints | Endpoint | Purpose | Response | | --- | --- | --- | | `POST /api/v3/githome/imports` | Start an import | `201` with the import | | `GET /api/v3/githome/imports` | The imports you started (not the repositories of an organization import), newest first, up to 100 | `200` with a list | | `GET /api/v3/githome/imports/{id}` | One import, with `children` for an organization import | `200`, or `404 import not found` | | `POST /api/v3/githome/imports/{id}/cancel` | Cancel a draft, queued or running import (an organization import cancels its queued and running repositories) | `200` with the import | | `POST /api/v3/githome/imports/{id}/retry` | Run a failed or cancelled import again; body `{"github_token": "ghp_..."}` (optional) | `202` with the import | | `POST /api/v3/githome/imports/{id}/selection` | Choose the repositories of a draft organization import (created in the web form) and start it; body `{"repositories": ["website", "docs"]}` | `202` with the import | You can read an import if you started it, or if you are a person who administers the account it imports into. The same people can cancel it. Only whoever started it can retry it, except that a person who may import into the target can take over the retry of an agent's import (see [Retries, cancelling and the repository lock](#retries-cancelling-and-the-repository-lock)). Poll an import until it finishes: ```sh while :; do s=$(curl -fsS https://git.pkgforge.dev/api/v3/githome/imports/$ID -H "Authorization: Bearer ghome_..." | jq -r .status) echo "$s"; case "$s" in succeeded|failed|cancelled) break;; esac; sleep 10 done ``` See the [REST API reference](https://git.pkgforge.dev/docs/api) for every endpoint. ## Import over MCP The [MCP server](https://git.pkgforge.dev/docs/agents/mcp) has three import tools: | Tool | Read-only | What it does | | --- | --- | --- | | `start_github_import` | No | Start a single-repository import. Arguments: `source` and `owner` (required), `name`, `visibility` (`keep`, `private`, `public`), `github_token`, `github_api_url`. Returns the [import object](#the-import-object). | | `get_import` | Yes | An import by `id`: status, steps, warnings, error and, for an organization import, its repositories | | `list_imports` | Yes | The imports you started, newest first | `start_github_import` imports with every option on. An agent's import never bypasses push protection and skips variables, secret names and environments (see [Agents and imports](#agents-and-imports)). `start_github_import` needs a `write` or `admin` token, like every tool that isn't read-only. ```sh curl -s https://git.pkgforge.dev/mcp \ -H "Authorization: Bearer $GITHOME_TOKEN" -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"start_github_import","arguments":{"source":"acme/website","owner":"acme"}}}' ``` Then call `get_import` with the returned `id` every minute or so until `status` is `succeeded`, `failed` or `cancelled`. ## What comes across | Data | What is imported | | --- | --- | | Repository | Description, homepage, topics (up to 20), default branch, archived state, and visibility as you chose | | Branches and tags | Every branch and tag. GitHub merge queue branches (`gh-readonly-queue/*`), `refs/pull//merge`, notes and other refs are skipped. | | Pull request heads | Each pull request's head commit, kept as `refs/pull//head`, also for merged and closed pull requests and pull requests from forks | | Git LFS | Every LFS object GitHub serves for the repository | | Issues | Number, title, body, author, assignees, labels, milestone, open or closed with its reason (`completed`, `not_planned`, `reopened`, `duplicate`), locked state and original dates | | Pull requests | Number, title, body, author, base and head branch, head commit, draft state, open, closed or merged, merge commit, who merged it, requested reviewers (open pull requests), labels, milestone and original dates | | Comments | Conversation comments on issues and pull requests, with author and dates | | Reviews | Approve, request changes, comment and dismissed reviews with body, commit and date (pending reviews are skipped). They never count as approvals. | | Review comments | Line comments with path, line, side, commit, review and reply threading | | Labels | Name, color and description | | Milestones | Number, title, description, state, due date, creator and dates | | Branch protection | Classic rules (see [Branch protection rules](#branch-protection-rules)) | | Actions variables | Repository variables with their values | | Secrets | Names only: repository secrets and environment secrets (organization secrets for organization imports) | | Environments | Name, deployment branch policy, custom branch patterns, and environment variables | | Organization variables | For an organization imported into a Githome organization: variables the Githome organization doesn't have yet | | Releases | Tag, target, name, notes, draft and pre-release state, author, dates, and assets up to 2 GiB each with their download counts | Issue and pull request numbers are kept, gaps and all. New issues and pull requests on Githome continue after the highest imported number, so links like `#123` in old text still point at the right place. ### Branch protection rules Each protected branch's classic rule becomes a Githome rule for the same branch name: **Require a pull request before merging**, required approvals, dismissing stale approvals, required status checks, force pushes and deletions allowed, linear history, and whether rules apply to admins. Required checks are renamed to the names Githome's workflows report (` / `), matched by job, so a rule that required `build` on GitHub requires `CI / build` here. Check them under **Settings → Branch protection** after the import. Repository rulesets aren't imported. ### Variables, secret names and environments - Repository variables are imported with their values. Names that start with `GITHUB_` or aren't valid variable names are skipped. - Secret **values are never read and never copied**: GitHub doesn't reveal them, and the importer doesn't try. Only names are listed, in the summary and on the import's page, for an admin to set by hand. Environment secret names appear as `/`. - Environments are created with their branch policy and variables; their secrets are listed by name only. - In an organization import into a Githome organization, the GitHub organization's variables are added to the Githome organization when it has no variable of that name. Existing ones are left alone (`Organization variable NPM_REGISTRY already exists and was left unchanged.`). Organization variables are shared by every repository of the organization; a repository variable of the same name wins. So only GitHub organization variables available to all repositories are copied. One limited to private or selected repositories on GitHub is skipped with a warning: `Organization variable NPM_TOKEN is limited to selected repositories on GitHub and was not copied; organization variables on Githome reach every repository, so add it to the repositories that need it.` ### Releases and assets Releases keep their tag, notes, dates and author. Importing a release creates no tag (the tags came with the Git data), starts no `release` workflows and sends no webhook. Assets are copied with their names, labels, content types and download counts; an asset with an unsafe file name, over 2 GiB, or on a host the server may not download from is skipped with a warning such as `Release v1.0.0: could not import asset "app.zip": ...`. ## What doesn't come across - **Secret values** of any kind. Set them again yourself (see [Set secret values](#set-secret-values)). - **Accounts.** No Githome accounts are created for GitHub users. See [People: linked accounts and mannequins](#people-linked-accounts-and-mannequins). - **Reactions**, wikis, projects, discussions, GitHub Pages, packages, webhooks, deploy keys, collaborators and teams, repository rulesets, Actions run history, and GitHub Apps. - **Required reviewers and wait timers** on environments. Set them again under Settings → Environments, with Githome people (see [Required reviewers and wait timers](https://git.pkgforge.dev/docs/actions/environments#required-reviewers-and-wait-timers)). - **Auto-merge** on open pull requests. Turn it on again on Githome (see [Auto-merge](https://git.pkgforge.dev/docs/collaboration/pull-requests#auto-merge)). - **Pull request heads whose fork was deleted on GitHub.** The pull request is imported but has no head commit (`3 pull requests have no head commit (their fork was deleted on GitHub): #12, #15, #40`). - **Anything a GitHub token couldn't read**, listed under **Warnings**. ## People: linked accounts and mannequins No accounts are created during an import. Each GitHub user who appears in the imported data (authors, commenters, reviewers, assignees, requested reviewers, who merged) is either mapped to a Githome account or shown as a mannequin. ### Mannequins A mannequin is a placeholder for a GitHub user who has no linked Githome account. It carries the history but isn't an account: it can't sign in or do anything on Githome, and its imported reviews never count as votes. | Where | How a mannequin appears | | --- | --- | | Web UI | The GitHub login with its picture and a **GitHub** badge, not linked, with the tooltip "Imported from GitHub; not linked to a Githome account" | | REST API | A user object with `login` `github:`, `type` `"Mannequin"`, and `html_url` and `url` pointing at the GitHub profile | | Assignees, requested reviewers, merged by | Stored as `github:` | | Issue search | `author:github:diffy` finds the mannequin's issues; `author:diffy` finds only the Githome account `diffy` | | Squash merges | A squash commit for a pull request a mannequin opened is authored as `diffy `, never as a Githome address | A deleted GitHub user appears as `ghost`. ### Link your GitHub account Linking proves that you control a GitHub account, so imports attribute that account's work to you. Link it **before** you import: links are applied as an import runs, and work already imported stays with the mannequin. In the web UI, go to **Settings → Linked accounts** (`https://git.pkgforge.dev/settings/linked-accounts`), the **Linked GitHub accounts** page. With a gist (no token needed): 1. Under **Step 1 · get a code**, leave **GitHub Enterprise API URL** blank for github.com (or enter your Enterprise API URL) and click **Get my code**. The code looks like `githome-link-3f9a...`. It is the same every time for your account and that host. 2. On GitHub, create a **public** gist whose description or one of whose files contains the code. 3. Under **Step 2 · verify your gist**, enter **Your GitHub username on github.com** and click **Verify and link**. You see "GitHub account linked." Githome reads your public profile and public gists without any token, from the API host you named, and links the account only when it finds the code. It looks at up to 100 of your gists (and reads the contents of up to 20). You can delete the gist afterwards. With GitHub OAuth, when the deployment has a GitHub OAuth app configured (`GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET`): the page shows **Link with GitHub**. Click **Continue to GitHub**, authorize read-only access to your profile (`read:user`), and you come back linked. The OAuth flow links github.com accounts only; its state is bound to your account, so a callback can't be replayed for someone else. To remove a link, click **Unlink** next to it and confirm. Only people can link accounts (`only people can link GitHub accounts`); agents can't. With the REST API (a token with the `admin` scope that isn't restricted to repositories): ```sh # Step 1: get the code (api_url is optional; default github.com) curl -X POST https://git.pkgforge.dev/api/v3/githome/user/linked-accounts/github/challenge \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" -d '{}' # {"nonce": "githome-link-...", "apiBase": "https://api.github.com", "host": "github.com", "gistsUrl": "https://api.github.com/gists"} # Step 2: after creating the public gist curl -X POST https://git.pkgforge.dev/api/v3/githome/user/linked-accounts/github \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" -d '{"login": "diffy"}' # 201 {"id": "...", "host": "github.com", "login": "diffy"} ``` | Endpoint | Purpose | | --- | --- | | `GET /api/v3/githome/user/linked-accounts` | Your links: `id`, `host`, `apiBase`, `login`, `externalId` (GitHub's numeric user id), `createdAt` | | `POST /api/v3/githome/user/linked-accounts/github/challenge` | Your code for a host; body `{"api_url": "..."}` (optional) | | `POST /api/v3/githome/user/linked-accounts/github` | Verify the gist and link; body `{"login": "diffy", "api_url": "..."}` | | `DELETE /api/v3/githome/user/linked-accounts/{id}` | Remove one of your links (`204`) | | `DELETE /api/v3/githome/admin/linked-accounts/{id}` | Moved to the dash: it answers 403, and the page **GitHub links** of the dash removes anyone's link, recorded in the audit log as `account.link_cleared` | Linking and unlinking are audited as `account.link_github` and `account.unlink_github`. ### How links are matched - A link stores GitHub's **numeric user id**, not only the login, and imports match by that id. Renaming a GitHub account, or someone else taking an old login, can't move work to the wrong person. - Links are kept per GitHub host (the full API base), so a github.com link and an Enterprise link are separate even if the logins match. - One GitHub account can be linked to only one Githome account (`GitHub user diffy is linked to another Githome account`). One Githome account can link several GitHub accounts. - Only links of active accounts are used. The summary lists which GitHub users were mapped (`people.linked`) and which became mannequins (`people.imported`). ### Imported reviews never count as approvals Imported reviews are history, not votes. A review imported from GitHub never counts toward required approvals and never blocks a merge, even when its author is a linked account and even if it was an approval. A pull request still open after the import needs a fresh review on Githome to be approved. ## Secrets in old history Imported history goes through [push protection](https://git.pkgforge.dev/docs/security/push-protection) like any push. When old commits contain something that looks like a credential, the `secrets` option decides: | Option | What happens | | --- | --- | | **Import with an audited bypass** (`bypass`, the default) | The history is imported anyway, because it is already on GitHub. The push carries the reason `Imported from GitHub acme/website`, is audited as `push.secret_bypassed` with the import and the blobs, and the import's page lists each finding under **Possible secrets in history (rotate these)** (`summary.findings`, with the file path where one was found). Rotate those credentials. | | **Stop the import** (`stop`) | The import fails at the Git step so you can clean the history first. | A bypass works only for a person who is an admin of the target repository and started the import with an `admin`-scoped token or from the web. Otherwise (an agent, or a `write` token) the import fails with `Push protection found possible secrets in the history (AWS access key). Only a person who administers the target can import them with an audited bypass (agents and write-scoped tokens cannot); start a new import as such a person.` **Agents never bypass push protection.** An import started by an agent always uses `stop`, whatever it asks for. A retry keeps the original options, so it can't switch from `stop` to `bypass`. After a stop, rotate the credentials, then start a new import with `bypass` as an admin (into a new name, or after deleting the partly imported repository), or clean the history on GitHub first. ## Limits | Limit | Value | | --- | --- | | Imports running at once | Per account that starts them and per target account: at most 3 single-repository imports (`too many repository imports are already running (at most 3 at a time); wait for one to finish`) and 1 organization import, drafts included (`an organization import is already in progress (at most 1 at a time); wait for it to finish or cancel it`). Repositories inside an organization import don't count toward the 3. | | Repository size | 10 GB by default, as GitHub reports it; a single-repository import over it is refused up front with `the repository is about 12 GB, over the 10 GB import limit; ask an administrator to raise IMPORT_MAX_REPO_KB or split the repository`. In an organization import, a repository over it fails with the same message before anything is copied, and the others carry on. The deployment sets `IMPORT_MAX_REPO_KB`. | | Git transfer | 6 hours. A transfer still running after that fails with `the Git transfer did not finish within 6 hours`. A failed transfer is tried a second time automatically. | | Single Git object | 100 MB (the push limit). A larger blob can't be imported. | | Repositories per organization import | 1,000 | | Concurrency of an organization import | 1 to 8, default 3 | | Organization import duration | The organization import waits up to a week for its repositories | | Draft organization imports | Cancelled after 7 days (`draft expired`), and the GitHub token erased | | Release asset | 2 GiB each | | Warnings kept per import | 500 | ## Retries, cancelling and the repository lock **Cancel** an import with **Cancel import** on its page (confirm "Cancel this import?"), or `POST /api/v3/githome/imports/{id}/cancel`. Its Git transfer is stopped, its credentials are revoked and the repository lock is released. Cancelling one repository of an organization import starts the next queued one. Cancelling a finished import fails with `the import already succeeded` (or `failed`, `cancelled`). **Retry** a failed or cancelled import with **Retry this import** on its page, or `POST /api/v3/githome/imports/{id}/retry`: - Whoever started the import can retry it. The one exception is an import an agent started: a person who may import into the target (its owner, or an owner or admin of the target organization) can retry it too, and should once the repository exists. Anyone else gets `404 import not found`. - Give the GitHub token again for a private repository (or for LFS, variables and protection): the first run's token was deleted when it ended. Leave it out for a public repository. - Retry the whole organization import, not one of its repositories (`retry the organization import this repository belongs to`). Its failed and cancelled repositories are retried; those that failed because the name already existed are not. - The options can't change on a retry. - Finished work isn't repeated or duplicated: steps write by GitHub id, and the Git transfer only sends what the repository doesn't have yet. - An agent can't retry once the repository was created (`an agent cannot retry an import after the repository was created; a person who administers acme must retry it`). A person who administers the target retries it with **Retry this import** or the API, giving the GitHub token again if the source is private. **The repository lock.** From the moment the import creates the repository until it finishes, fails or is cancelled, only the import may write to it. Any other push gets `repository is locked by an import in progress`, and any other write through the REST API, the web UI or MCP gets `423 repository is locked by an import in progress; try again when it finishes, or cancel the import`. Watching the repository still works, and so do Actions secrets and variables, environments (with their secrets and variables), and collaborators and invitations. The import never writes secret values; its variables step writes GitHub's values, so a variable you set before that step under the same name ends with GitHub's value. The import itself may only create refs or move refs it wrote. A retry claims the repository again only when it holds nothing the import didn't write. If anyone pushed a branch, opened an issue, added a label, a protection rule or a release in the meantime (for example after the import failed and released the lock), the retry fails with `repository already holds content not written by this import; start a new import`. A failed or cancelled import leaves the partly imported repository in place; delete it before importing again under the same name. ## Agents and imports Agents can start imports over MCP, the REST API or the CLI, with these rules: - **Only where its owner may import.** An agent owned by a person imports into that person's own account or an organization the person owns or administers. An agent owned by an organization imports into that organization. Otherwise `agents can import only where their owner may: the owner's own account or an organization the owner administers, not `. - **The agent's maximum role must be at least `write`** (`this agent's policy does not allow writing; an import needs at least write`), and its token needs the `write` scope. - **Never a push protection bypass.** The `secrets` option is forced to `stop`. - **No variables, secret names or environments.** The **Variables and secret names** step, and an organization import's **Organization variables and secret names** step, are skipped with `skipped (agents cannot manage variables)`. A person imports or sets those afterwards. For people, the right to manage variables is checked again when that step runs. - **No retry after the repository exists.** A person who administers the target takes the retry over. - **No secret values**, ever. Agents can't set secrets anywhere; a person with admin access sets them. - An agent sees and lists only the imports it started. Everything else (Git data, issues, pull requests, reviews, labels, milestones, branch protection, releases) is imported as for a person. See [Agents](https://git.pkgforge.dev/docs/agents/overview). ## After the import ### Set secret values The import lists secret names; set each value from where you keep it (a password manager, your cloud provider's console). Repository admins who are people can: - Click **Set secret values** on the import's page. It lists each repository secret name with a `set` or `empty` badge, a **Value** field and **Save**. - Use the CLI, which prompts for the value without echoing it: ```sh githome secret set NPM_TOKEN -R acme/website printf '%s' "$NPM_TOKEN" | githome secret set NPM_TOKEN -R acme/website githome secret set SENTRY_DSN --org acme # organization secret ``` - Use the API (see [Move secrets and variables](#move-secrets-and-variables)). Environment secrets (listed as `production/DEPLOY_KEY`) are set with the environments API, as in [Environments and their secrets](#environments-and-their-secrets). You don't have to wait for the import to finish: secrets, variables, environments and collaborators can be set while it is still running (see [Retries, cancelling and the repository lock](#retries-cancelling-and-the-repository-lock)). Set them before your first push, because that push starts the imported workflows. ### Check the rest 1. Under **Settings → General**, check the default branch, description and visibility. 2. Under **Settings → Branch protection**, check the imported rules and their required check names. 3. Under **Settings → Collaborators**, add people, and invite your team to the organization. 4. Recreate webhooks under **Settings → Webhooks**. 5. Push a commit and check the result. The forge CI is dormant, so no workflow run starts. 6. If the repository landed under the wrong owner or name, [transfer](https://git.pkgforge.dev/docs/repositories/overview#transfer-a-repository) or [rename](https://git.pkgforge.dev/docs/repositories/overview#rename-a-repository) it once the import has finished (a transfer is refused while the import runs). The old Githome URL keeps working. 7. Agent settings in branch protection (**Allow agents to push directly**, **Allow agents to merge pull requests**, **Allow agents to land pull requests through auto-merge** and its approval waiver) never come across with an import; an admin sets them here. ## Import from GitLab, Forgejo or Gitea The server-side importer reads GitLab, Forgejo, Gitea and Codeberg too. It copies the Git history and the records of a repository. You start an import from the web or the REST API, and nothing runs on your machine. ### What comes across from another forge | Record | GitLab | Forgejo, Gitea and Codeberg | | --- | --- | --- | | Branches and tags | Yes | Yes | | Pull requests | Merge requests, with their heads | Pull requests, with their heads | | Issues | Yes, with their numbers, but no confidential issue | Yes, with their numbers | | Comments | Notes, but no system note and no internal note | Comments of issues and pull requests | | Comments on lines of a diff | Diff notes | No | | Reviews | Approvals, as approving reviews | Reviews, with their state | | Labels and milestones | Yes, with the milestones of the parent groups | Yes | | Releases | Yes, with no asset | Yes, with no asset | | Branch protection, Actions variables, Git LFS objects | No | No | A public project of GitLab whose code, issues or merge requests members alone can read counts as private. So the visibility `keep` makes its repository private. ### Numbers of another forge Forgejo and Gitea number issues and pull requests in one sequence, as GitHub and Githome do, so each keeps its number. GitLab numbers its issues (`#3`) and its merge requests (`!3`) in two sequences. An issue keeps its number. A merge request takes the highest issue number plus its own number. For example, in a project whose highest issue is `#40`, the merge request `!3` becomes pull request `#43`. The import counts the issues once, at its start. An issue that GitLab makes after that is not imported, because a merge request holds its number. The text of a comment is copied as it is, so a reference such as `!3` in it still names the merge request of GitLab. ### People of another forge A person of the source has no Githome account, so the import keeps the person as an imported person, named `host/login`, for example `gitlab.com/alice`. An instance under a path keeps its path, as in `example.com/gitlab/alice`. - The page shows the name and, as its badge, the host. - The REST and GraphQL APIs give the person as a `Mannequin` with the login `github:gitlab.com/alice`, whose profile is on that host. A search for the person is `author:github:gitlab.com/alice`. - A squash of a pull request of the person writes a noreply address of Githome, not of GitHub. No person of another forge is linked to a Githome account. ### Import from another forge on the web Open the import form as [Import from the web](#import-from-the-web) describes. In **From**, choose GitLab, Forgejo or Gitea, or Codeberg. In **Address of the instance**, give the address of a self-hosted instance, for example `https://gitlab.example.com`. GitLab without an address is `gitlab.com`, and Codeberg has its own. Give the token of the forge in **Token**. ### Import from another forge with the REST API Send the forge, the address and the token with the fields of an import of GitHub: ```bash curl -X POST https://git.pkgforge.dev/api/v3/githome/imports \ -H "Authorization: token $GITHOME_TOKEN" \ -H "Content-Type: application/json" \ -d '{"forge":"gitlab","forge_url":"https://gitlab.com","forge_token":"'"$GITLAB_TOKEN"'","source":"group/subgroup/project","owner":"ana"}' ``` | Field | Value | | --- | --- | | `forge` | `gitlab`, `forgejo`, `gitea` or `codeberg`. Without it, the import reads GitHub. | | `forge_url` | The address of the instance: HTTPS on a public host and the standard port. GitLab without it is `https://gitlab.com`. Forgejo and Gitea need it. Codeberg takes none. | | `forge_token` | Required. A token that reads the source. See [Tokens of another forge](#tokens-of-another-forge). | | `source` | `owner/name` for Forgejo and Gitea, and `group/subgroup/project` for GitLab, or a URL of the repository on the instance. | | `source_owner` | In place of `source`: a group, a subgroup, an organization or a user, whose repositories the import reads. A group of GitLab gives its own projects, and not those of its subgroups. | A request with `forge_url` or `forge_token` and no `forge` is turned down, and so is a request with `github_token` or `github_api_url` and another forge. A source URL on another host than the instance is turned down too. A retry of the import takes its token again as `forge_token`. ### Tokens of another forge A token goes only to the host of the instance, and it is deleted when the import ends. - **GitLab:** a personal access token with the scopes `read_api` and `read_repository`. - **Forgejo and Gitea:** a token with the scopes `read:repository` and `read:issue`. An import of an organization or a user needs `read:organization` and `read:user` too. ### How the Git data of another forge comes across The importer fetches the branches, the tags and the heads of the pull requests with the pull side of the mirror driver of the forge, inside Githome. A pack is checked and scanned for secrets as a pull mirror checks a pack. The option for secrets in old history works as for GitHub: `stop` turns the import down, and `bypass` imports the history with an audited bypass. A bypass needs a person who administers the target and an `admin` token. ### Limits of another forge - The Git data of one import comes in one pack of at most 100 MiB. A repository of Forgejo or Gitea over that size is turned down at the start. GitLab gives no size, so a larger project fails at the Git step. - Git LFS objects, branch protection and Actions variables are not imported. The steps of branch protection and Actions variables say so, and a warning names Git LFS. - The assets of a release are not imported. - The command-line client and MCP start imports of GitHub alone. ## Move with plain Git If you only need the code, copy it with Git (2.26 or newer). Create an empty repository on Githome first (web: `https://git.pkgforge.dev/new`, or CLI), using the same default branch name as on GitHub: ```sh githome repo create website --org acme --private --default-branch main ``` Then copy every branch and tag: ```sh git clone --mirror https://github.com/acme/website.git cd website.git git push https://git.pkgforge.dev/acme/website.git 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*' ``` Push branches and tags explicitly rather than with `git push --mirror`: a mirror clone from GitHub also contains GitHub's `refs/pull/*` refs, and Githome rejects pushes to `refs/pull/` (`refs/pull/ is managed by Githome for pull requests`). If the push is over 100 MB, it fails with `push exceeds 100 MB; split it into smaller pushes`. Push the history in steps, oldest first: ```sh # Push the default branch in chunks of 2,000 commits, then everything else for sha in $(git rev-list --reverse --first-parent main | awk 'NR % 2000 == 0'); do git push https://git.pkgforge.dev/acme/website.git "$sha:refs/heads/main" done git push https://git.pkgforge.dev/acme/website.git 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*' ``` If push protection blocks the push because old commits contain something that looks like a credential, rotate that credential. A repository admin (a person, not an agent) using an `admin`-scoped token can then push anyway with a reason, which is audited: ```sh git push -o allow-secrets="historic keys, all rotated" https://git.pkgforge.dev/acme/website.git 'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*' ``` If GitHub's default branch isn't the one you created the repository with, change it under **Settings → General → Default branch**. ## Move releases The importer copies releases and their assets. If you moved the code with plain Git or `--local`, recreate releases with the GitHub-compatible releases API once the tags are on Githome. This script uses GitHub's `gh` CLI to read each release and `curl` to recreate it, oldest first so the newest ends up as the latest release, and copies its assets: ```sh export GITHOME_TOKEN=ghome_... # write scope or higher SRC=acme/website # on GitHub DST=acme/website # on Githome API=https://git.pkgforge.dev/api/v3 gh release list -R "$SRC" --limit 1000 --json tagName --jq 'reverse | .[].tagName' | while read -r tag; do gh release view "$tag" -R "$SRC" --json tagName,name,body,isDraft,isPrerelease \ --jq '{tag_name: .tagName, name: .name, body: .body, draft: .isDraft, prerelease: .isPrerelease}' > release.json id=$(curl -fsS -X POST "$API/repos/$DST/releases" \ -H "Authorization: Bearer $GITHOME_TOKEN" -H "content-type: application/json" \ --data-binary @release.json | jq -r .id) rm -rf assets && mkdir assets gh release download "$tag" -R "$SRC" -D assets 2>/dev/null || true for f in assets/*; do [ -f "$f" ] || continue name=$(jq -rn --arg n "$(basename "$f")" '$n | @uri') curl -fsS -o /dev/null -X POST "https://git.pkgforge.dev/api/uploads/repos/$DST/releases/$id/assets?name=$name" \ -H "Authorization: Bearer $GITHOME_TOKEN" -H "content-type: application/octet-stream" \ --data-binary @"$f" echo "$tag: uploaded $(basename "$f")" done done ``` Things to know: - Push the tags first. If a release's tag is missing on Githome, publishing the release creates the tag on the default branch, which is probably not the commit you want. - Unlike imported releases, each release published this way sends a `release` webhook event. (A repository's `on: release` workflows start no run on git.pkgforge.dev, where the forge CI is dormant.) - Release notes, titles, draft and pre-release state are copied. Authors and dates are not: the releases are created by you, now. - An asset uploaded through the API can be up to 100 MB. - Source code archives (**Source code (zip)** and **Source code (tar.gz)**) are not assets: Githome builds them from the tag. See [Source code archives](https://git.pkgforge.dev/docs/repositories/overview#source-code-archives). See [Releases](https://git.pkgforge.dev/docs/collaboration/releases) for the API in full. ## Move Git LFS files The importer copies Git LFS objects. Neither `git clone --mirror` nor `githome migrate github --local` does: they copy only the pointers. If you moved the code that way and the repository uses LFS, copy the files from a clone that can fetch them: ```sh git clone https://github.com/acme/website.git website-lfs cd website-lfs git lfs fetch --all origin git lfs push --all https://git.pkgforge.dev/acme/website.git ``` Files over 100 MB can't be uploaded to Githome. See [Git LFS](https://git.pkgforge.dev/docs/repositories/git-lfs). ## Move secrets and variables ### Secrets GitHub never shows secret values, so you set them again on Githome. Get the list of names from the import's summary, from `githome migrate github`'s output, or with GitHub's CLI (`gh secret list -R acme/website`). Then set them as in [Set secret values](#set-secret-values), or with the API (an admin role on the repository, and not an agent): ```sh curl -X PUT https://git.pkgforge.dev/api/v3/repos/acme/website/actions/secrets/NPM_TOKEN \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{"value": "npm_..."}' ``` Unlike GitHub, the API takes the plain value over HTTPS; there is no public-key encryption step, and a sealed-box `encrypted_value` is refused (send `value` instead). Secret names use letters, digits and `_`, are stored in upper case, and can't start with `GITHUB_`. To copy secrets without handling the values yourself, let a GitHub workflow send them, as in [Keep GitHub as upstream](#keep-github-as-upstream-and-mirror-to-githome). ### Environments and their secrets Githome has deployment environments with their own secrets, variables and branch policies, like GitHub. The importer creates them with their branch policies and variables. They have no page in the web UI yet: change them, and set their secrets, with the REST API, as a repository admin who is a person (agents can't manage environments, secrets or variables). ```sh # Create the environment (the importer already did if it came from GitHub) curl -X PUT https://git.pkgforge.dev/api/v3/repos/acme/website/environments/production \ -H "Authorization: Bearer ghome_..." # Add its secrets curl -X PUT https://git.pkgforge.dev/api/v3/repos/acme/website/environments/production/secrets/DEPLOY_KEY \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{"value": "..."}' # Add its variables curl -X POST https://git.pkgforge.dev/api/v3/repos/acme/website/environments/production/variables \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{"name": "DEPLOY_URL", "value": "https://www.example.com"}' ``` Jobs with `environment: production` then get these secrets and variables. When an environment without a branch policy gets its first secret, it is limited to protected branches, so add a [branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection) rule for the branch you deploy from (or set the environment's branch policy). Add required reviewers and a wait timer under Settings → Environments. See [Environments](https://git.pkgforge.dev/docs/actions/environments). ### Variables The importer and `githome migrate github --local` copy repository variables. To copy them yourself: ```sh gh variable list -R acme/website --json name,value --jq '.[] | [.name, .value] | @tsv' | while IFS=$'\t' read -r name value; do githome variable set "$name" --body "$value" -R acme/website done ``` Organization variables are shared by every repository of a Githome organization; a repository variable of the same name wins. An organization import copies them. Owners and admins of the organization (people, with an `admin`-scoped token for changes) manage them with `GET` and `POST /api/v3/orgs/{org}/actions/variables` and `GET`, `PATCH` and `DELETE /api/v3/orgs/{org}/actions/variables/{name}`: ```sh curl -X POST https://git.pkgforge.dev/api/v3/orgs/acme/actions/variables \ -H "Authorization: Bearer ghome_..." -H "content-type: application/json" \ -d '{"name": "NPM_REGISTRY", "value": "https://registry.npmjs.org"}' ``` See [Secrets and variables](https://git.pkgforge.dev/docs/actions/secrets-and-variables). ## Update remotes and local clones Everyone with a clone points it at Githome: ```sh git remote set-url origin https://git.pkgforge.dev/acme/website.git git fetch origin ``` Or keep GitHub as a second remote while you move: ```sh git remote rename origin github git remote add origin https://git.pkgforge.dev/acme/website.git git fetch origin git branch --set-upstream-to=origin/main main ``` Git asks for a password the first time: use a Githome token, or run `githome auth setup-git` once so Git gets it from the CLI. See [Git over HTTPS](https://git.pkgforge.dev/docs/repositories/git). Editors clone with the plain HTTPS URL of the repository (`https://git.pkgforge.dev/acme/website.git`), signed in with a token or `githome auth setup-git`. There is no editor extension. Also update anything else that holds the old URL: CI and deploy scripts, package manifests (`repository` fields), submodule URLs in `.gitmodules`, badges and links in READMEs. ## Workflows > The forge CI of git.pkgforge.dev is dormant: no workflow runs there now, whatever a push or an import does. Your workflow files come across as files, and the code that reads them stays in githome. The table below is for a deployment with the CI on. Githome's Actions code reads GitHub Actions workflows from `.github/workflows/` as they are: the same triggers, expressions, matrices, `needs`, job outputs, caches, artifacts, secrets, `GITHUB_TOKEN` permissions, OIDC, `actions/checkout`, `actions/setup-node`, `setup-python`, `setup-go`, `actions/github-script`, and remote JavaScript and composite actions. Things to check after the move, where the CI is on: | If a workflow... | Do this on Githome | | --- | --- | | Has jobs that mostly wait (deploys, API calls, polling), or runs on every push | Cancel superseded pull request runs with a `concurrency` group. See [Runners](https://git.pkgforge.dev/docs/actions/runners). | | Uses `runs-on: windows-*` or `macos-*` | Githome has no Windows or macOS hosted runners. Run the job on a self-hosted runner (`githome runner`). See [Runners](https://git.pkgforge.dev/docs/actions/runners). | | Uses `actions/github-script` | Works with the REST API (`github.rest.*`) and the job's token. `github.graphql` works for the issues, pull requests and CI that Githome's [GraphQL API](https://git.pkgforge.dev/docs/reference/graphql-api) answers. | | Relies on `GITHUB_TOKEN` writing (comments, labels, statuses, releases, pushes) without a `permissions:` block | Repositories created on Githome, imported ones included, give the job token GitHub's restricted default, `contents` and `packages` read. Add a `permissions:` block (for example `contents: write`, `issues: write`, `pull-requests: write`) to the workflow or job, or have an admin set the repository default to write. Each endpoint needs its permission, as on GitHub; a missing one gets `403 Resource not accessible by integration`. See [Workflow permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions). | | Pushes commits or tags using `GITHUB_TOKEN` | Works with `permissions: contents: write`, as on GitHub, within branch protection. The token can't change files under `.github/workflows/`, and a push made with it starts no new `push` workflows. | | Opens or approves pull requests using `GITHUB_TOKEN` | Refused until a repository admin allows it (`can_approve_pull_request_reviews` in the workflow permissions setting, off by default, as GitHub's **Allow GitHub Actions to create and approve pull requests**). Approvals from the token never count toward required approvals. | | Uses environments (`environment: production`) | The importer creates the environments and their variables; set their secrets with the API (see [Environments and their secrets](#environments-and-their-secrets)). Required reviewers and wait timers don't come across; set them again under Settings → Environments. | | Runs on `release` or `repository_dispatch` | Where the CI is on, publishing a release starts `on: release` workflows, and `POST /api/v3/repos/acme/website/dispatches` starts `on: repository_dispatch` workflows. On git.pkgforge.dev, a dispatch is refused with "CI is off on this deployment". | | Checks out Git LFS files (`lfs: true`) | Works as on GitHub. See [Git LFS](https://git.pkgforge.dev/docs/repositories/git-lfs). | | Publishes images to `ghcr.io` | Use your instance's registry (`git.pkgforge.dev` here) instead. See [Container registry](https://git.pkgforge.dev/docs/packages/container-registry). | | Hard-codes `github.com` or `api.github.com` | Use `${{ github.server_url }}` (`https://git.pkgforge.dev`) and `${{ github.api_url }}` (`https://git.pkgforge.dev/api/v3`). | | Should run only on one forge | Guard it with `if: github.server_url == 'https://github.com'` (or `'https://git.pkgforge.dev'`). | A job that uses an unsupported feature fails with a message saying so. `githome workflow validate` checks workflow files before you push. Full details are in [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). ## Scripts and tools that call GitHub's API Githome serves a GitHub-compatible REST API at `https://git.pkgforge.dev/api/v3`, with the same paths, JSON shapes, errors and `Link`-header pagination, so most scripts and Octokit-based tools only need a new base URL and a Githome token: ```js import { Octokit } from "@octokit/rest"; const octokit = new Octokit({ auth: process.env.GITHOME_TOKEN, baseUrl: "https://git.pkgforge.dev/api/v3" }); const { data } = await octokit.rest.repos.listReleases({ owner: "acme", repo: "website" }); ``` Inside workflows, `${{ github.api_url }}` is already `https://git.pkgforge.dev/api/v3`. Imported people without a Githome account come back as user objects with `"type": "Mannequin"` and a `github:` login, so tools that look up users by login should expect them. Differences to check, including endpoints and features that are not supported yet, are listed in the [REST API reference](https://git.pkgforge.dev/docs/reference/rest-api). The [GraphQL API](https://git.pkgforge.dev/docs/reference/graphql-api) covers repositories, issues, pull requests and CI, which is what the GitHub CLI needs (see [GitHub CLI and Claude Code](https://git.pkgforge.dev/docs/agents/github-cli)). ## Keep GitHub as upstream and mirror to Githome You can keep GitHub as the place where people push and review, and mirror every push to Githome with a GitHub Actions workflow that runs on GitHub. It copies every branch and tag, plus the secrets you list, to Githome on each push. The forge CI of git.pkgforge.dev is dormant, so Githome starts no run on the mirrored commits. Set it up: 1. Create the Githome repository (for example `acme/website`). 2. Create a Githome token with the `admin` scope for an account that is an admin of that repository. If you want force pushes to protected branches to go through, protection rules must let admins bypass them. 3. On GitHub, add it as a repository secret named `GITHOME_TOKEN`. 4. Add this workflow on GitHub as `.github/workflows/mirror-to-githome.yml`: ```yaml name: Mirror to Githome on: push: workflow_dispatch: permissions: contents: read # One mirror at a time, in push order. concurrency: group: mirror-to-githome cancel-in-progress: false jobs: mirror: # The mirrored copy of this file also exists on Githome; do nothing there. if: ${{ github.server_url == 'https://github.com' }} runs-on: ubuntu-latest env: GITHOME: https://git.pkgforge.dev TARGET: acme/website TOKEN: ${{ secrets.GITHOME_TOKEN }} steps: - name: Copy Actions secrets env: S_NPM_TOKEN: ${{ secrets.NPM_TOKEN }} S_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} run: | set -euo pipefail for name in NPM_TOKEN SENTRY_DSN; do v="S_$name" [ -n "${!v}" ] || { echo "::warning::secret $name is empty here; not copied"; continue; } jq -n --arg v "${!v}" '{value: $v}' | curl -fsS -o /dev/null -X PUT \ "$GITHOME/api/v3/repos/$TARGET/actions/secrets/$name" \ -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" --data-binary @- echo "secret $name copied" done - uses: actions/checkout@v4 with: fetch-depth: 0 # lfs: true # if the repository uses Git LFS - name: Push every branch and tag run: | set -euo pipefail git fetch -q --tags origin '+refs/heads/*:refs/remotes/origin/*' refs=$(git for-each-ref --format='+%(refname):refs/heads/%(refname:lstrip=3)' refs/remotes/origin | grep -v ':refs/heads/HEAD$') git -c "http.$GITHOME/.extraHeader=Authorization: Bearer $TOKEN" \ push -q "$GITHOME/$TARGET.git" $refs '+refs/tags/*:refs/tags/*' # If the repository uses Git LFS: # git lfs ls-files | grep -q . && git -c "http.$GITHOME/.extraHeader=Authorization: Bearer $TOKEN" lfs push --all "$GITHOME/$TARGET.git" ``` How it works: - The checkout fetches the full history, then every GitHub branch is pushed to the branch of the same name on Githome, with a leading `+` so GitHub always wins. Changes made directly on Githome to mirrored branches are overwritten. - Branches deleted on GitHub are not deleted on Githome. Delete them there by hand (`git push https://git.pkgforge.dev/acme/website.git --delete old-branch`). - The secrets step sends each value from GitHub's secret store, inside your own workflow, straight to Githome over HTTPS; values are never printed. List every secret your workflows use. Variables can be copied the same way with `vars.NAME` and the `actions/variables` endpoint. - The `if:` guard keeps the job from running anywhere but on GitHub, in case a forge with CI on ever runs the mirrored file. - If push protection blocks a mirrored push, a repository admin can let it through with `-o allow-secrets=` on the `git push` line, for example from a `workflow_dispatch` input. Leave it empty normally. ## Checklist 1. Get a Githome account and create the organization. 2. Link your GitHub account under **Settings → Linked accounts**, and ask your team to link theirs, so their work is attributed to them. 3. Create a GitHub token that can read the repositories (admin access for branch protection, variables and secret names). 4. Import: **Settings → Imports → Import from GitHub**, `githome migrate github acme/website --to acme/website`, or `githome migrate github-org acme --to acme`. 5. Read the import's **Warnings** and rotate anything under **Possible secrets in history (rotate these)**. 6. Set every secret listed (**Set secret values**), environment secrets with the API, and organization secrets with `githome secret set NAME --org acme`. 7. Check the default branch, description and visibility under **Settings → General**, and the imported rules under **Settings → Branch protection** (required check names are ` / `; see [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection)). 8. Add collaborators under **Settings → Collaborators**, and invite your team to the organization. 9. Recreate webhooks under **Settings → Webhooks**. Deliveries carry GitHub's `X-GitHub-Event` header and are signed with `X-Hub-Signature-256`, but check the payload fields your receiver uses. Failed deliveries (network errors, `408`, `429` and `5xx`) are retried up to five times with the same `X-GitHub-Delivery` ID, so make your receiver ignore a delivery ID it has already handled. See [Webhooks](https://git.pkgforge.dev/docs/repositories/webhooks). 10. If an outside CI system reported commit statuses or checks to GitHub, point it at `https://git.pkgforge.dev/api/v3` with a Githome token. Its status contexts and check names can be required checks in branch protection, as on GitHub. See [Checks and statuses](https://git.pkgforge.dev/docs/collaboration/checks-and-statuses). 11. Read [Workflows](#workflows): the forge CI of git.pkgforge.dev is dormant, so a push starts no run there now. 12. Create agent accounts for AI tools and connect them over MCP. See [Agents](https://git.pkgforge.dev/docs/agents/overview). 13. Update remotes on every clone, and URLs in scripts, manifests and READMEs. 14. When the team has moved, archive the GitHub repository or remove the mirror workflow. Checking the CI after the move: the forge CI is dormant, so use the checks that another CI system reports to Githome (step 10). ## Troubleshooting ### Starting an import | Message | Cause and fix | | --- | --- | | `GitHub repository acme/website was not found or the token cannot read it` | The name is wrong, or the repository is private and the GitHub token is missing or can't see it. | | `GitHub rejected the token (expired or revoked?)` | Create a new GitHub token. | | `acme has reached its storage limit of N bytes (...)` | The Githome owner is at its [storage quota](https://git.pkgforge.dev/docs/reference/limits#account-quotas). An import stores what it copies, so it is refused up front, and one that reaches the limit on the way stops with the same message. Free space or ask the superadmin to raise it, then retry. | | `no GitHub organization or user named acme` | Check the spelling, and `github_api_url` for Enterprise. | | `acme has no repositories to import` | The account has none the token can see, or the filters excluded all of them. | | `acme/website already exists; choose another name` | Pick another `name` (or **New repository name**), or delete the existing repository. | | `you can import only into your own account or organizations you administer, not acme` | Ask an owner of `acme` to make you an admin, or to run the import. | | `agents can import only where their owner may: ...` | The target isn't the owner's own account or an organization the owner administers (or, for an organization's agent, that organization). | | `starting an import needs a token with write or admin scope` | Use a `write` or `admin` token. | | `this token needs the write scope` or `this token is limited to repositories and can't change account settings` | Cancelling, retrying and choosing repositories need a `write` token that isn't restricted to repositories. | | `too many repository imports are already running (at most 3 at a time); wait for one to finish` | Wait for one to finish, or cancel one. | | `an organization import is already in progress (at most 1 at a time); wait for it to finish or cancel it` | Includes drafts waiting on **Choose repositories**. Finish or cancel it. | | `the repository is about N GB, over the 10 GB import limit; ...` | Split the repository, or on your own instance raise `IMPORT_MAX_REPO_KB`. | | `give either source (one repository) or source_owner (an organization or user)` | Send exactly one of them. | | `github_api_url is required when a github_token is given and the source names a GitHub Enterprise host` | Add `github_api_url` for that host, or pass `owner/name` as the source. | | `github_api_url must be on the same host as the source repository` | The API URL and the source URL name different hosts. | | `GitHub rate limit reached; continuing in N seconds` | Shown on a step while the importer waits; it continues by itself. At start time it comes back as `429`; try again later or use a GitHub token. | ### While an import runs | Message | Cause and fix | | --- | --- | | `Push protection found possible secrets in the history (...)` | See [Secrets in old history](#secrets-in-old-history). | | `a single Git object of N MB could not be pushed even on its own (...)` | One file in the history is too large for Githome to take in one push (the server's answer is in brackets). Remove it from history on GitHub (for example with `git filter-repo`), or move it to Git LFS, and import again. | | `pushes kept failing even in chunks of N KB (...)` | Githome kept refusing or dropping the transfer's pushes; the server's answer is in brackets. Retry the import; if it fails the same way, report it. | | `the Git transfer did not finish within 6 hours` | The repository is too large or GitHub was too slow. Retry, or split the repository. | | `the import container stopped before finishing (exit code ...)` | Not seen on git.pkgforge.dev, which runs no import container (a GitHub import stops earlier, at "no import container is configured"). The transfer is retried once automatically; after that, retry the import. | | `The Git transfer failed and is being retried: ...` (warning) | The first transfer failed and a second one started. Nothing to do. | | `repository is locked by an import in progress` (on a push), or `423 repository is locked by an import in progress; try again when it finishes, or cancel the import` | You wrote to a repository an import is still filling. Wait for the import to finish, or cancel it. Actions secrets and variables, environments and collaborators aren't locked: set them while the import runs. | | `repository already holds content not written by this import; start a new import` | Someone changed the repository between attempts. Start a new import under another name, or delete the repository first. | | `skipped (agents cannot manage variables)` | An agent started the import. A person sets variables and secrets afterwards. | | `skipped (you no longer administer the target)` | You lost admin rights on the target before the variables step ran. | | `Branch protection of main could not be read ...` | The GitHub token lacks admin access. Set the rule up under **Settings → Branch protection**. | | `Actions variables could not be read ...` (or `secrets`, `environments`) | Give the token admin access, or the fine-grained **Variables** and **Secrets** read permissions, and set the rest by hand. | | `N pull requests have no head commit (their fork was deleted on GitHub): ...` | Those pull requests are imported without their commits. Nothing to do. | | `the person or agent who started this import can no longer import into this account` | The starter lost the right to import there, or their account was disabled. | ### Retrying and cancelling | Message | Cause and fix | | --- | --- | | `import not found` | You didn't start the import (only the starter can retry, or for an agent's import a person who administers the target), or you can't see it. | | `only failed or cancelled imports can be retried` | The import is still running or succeeded. | | `retry the organization import this repository belongs to` | Retry the parent import. | | `an agent cannot retry an import after the repository was created; a person who administers must retry it` | A person who administers the target retries it. | | `the import already succeeded` (or `failed`, `cancelled`) | Only drafts and queued or running imports can be cancelled. | ### Linking a GitHub account | Message | Cause and fix | | --- | --- | | `create a PUBLIC gist whose description or a file contains githome-link-..., then try again` | The gist is missing, secret, or doesn't contain the exact code. | | `GitHub user diffy was not found` | Check the username and the host. | | `GitHub user diffy is linked to another Githome account` | Unlink it there first, or ask the superadmin to clear the link. | | `that is not a valid GitHub login` | Use the username, not an email address or URL. | | `invalid or expired OAuth state` | Start **Continue to GitHub** again from your own settings page. | ### Errors from the local import | Message | Cause and fix | | --- | --- | | `git clone --mirror failed: ...` | Git couldn't clone from GitHub. Check `GH_TOKEN` and that Git is installed. | | `warning: bulk push failed (...); pushing refs one at a time` | One push was too big or a ref was rejected. Check the refs listed as failed in the summary. | | A ref fails with `secret detected (push protection)` | Rotate the credential, then push that ref with plain Git and `-o allow-secrets=` as a repository admin, or use the server-side importer. | | A ref fails with `push exceeds 100 MB` | Push that branch's history in steps, as in [Move with plain Git](#move-with-plain-git), or use the server-side importer. | | `could not read ... from GitHub (403; the token may lack access)` | The GitHub token can't read that data. | | `agents cannot manage variables` or `agents may not push to protected or default branches` | `--local` needs a token of your own account, not an agent's. | --- # Guides > Short, task-focused guides to common jobs on Githome: moving GitHub Actions workflows, faster CI, releases with release-please, and AI coding agents with guardrails. Source: https://git.pkgforge.dev/docs/guides Each guide answers one question in a few steps and links to the pages that cover the details. | Guide | What it covers | | --- | --- | | [Move your GitHub Actions workflows to Githome](https://git.pkgforge.dev/docs/guides/move-github-actions-workflows) | What runs unchanged, runner labels and sizes, marketplace actions, secrets, caches, Docker, OIDC, environments, self-hosted runners for macOS, Windows and Arm, and a checklist. | | [Make your CI faster on Githome](https://git.pkgforge.dev/docs/guides/faster-ci) | Runner sizes and automatic sizing, caching, setup and Docker head starts, matrices, cancelling superseded runs. | | [Automate versions and releases with release-please](https://git.pkgforge.dev/docs/guides/release-please) | The release-please action and CLI on Githome: the workflow, permissions, CI on release pull requests and troubleshooting. | | [Give an AI coding agent its own account, with guardrails](https://git.pkgforge.dev/docs/guides/ai-agent-with-guardrails) | Create an agent and its token, what the server enforces, connecting Claude Code, Codex or any MCP client, reviewing and merging agent pull requests, and auditing what agents did. | Other task pages: [Quickstart](https://git.pkgforge.dev/docs/quickstart), [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github), [Deploy to Cloudflare Workers](https://git.pkgforge.dev/docs/actions/deploy-to-cloudflare-workers), [Merge on green automatically](https://git.pkgforge.dev/docs/collaboration/merge-on-green) and [Cloud agent environments](https://git.pkgforge.dev/docs/connect/cloud-agents). --- # Move your GitHub Actions workflows to Githome > Run your existing .github/workflows files on Githome: what runs unchanged, runner labels and sizes, secrets, caches, Docker, OIDC, environments, and what to change. Source: https://git.pkgforge.dev/docs/guides/move-github-actions-workflows > **Note:** The forge CI of git.pkgforge.dev is dormant: githome reads and validates workflow files, but starts no run, so a workflow does not run there now. This guide says what holds for the files, and what a deployment with the CI on would run. Most GitHub Actions workflow files are accepted by Githome without changes: Githome reads `.github/workflows/*.yml`, supports the same triggers, expressions, matrices, `needs`, caches, artifacts, secrets, OIDC and Docker, and downloads marketplace actions from GitHub as they are. On a deployment with the CI on, jobs with `runs-on: ubuntu-latest` run on hosted Ubuntu 24.04 runners. What you change is usually small: set your secret values again (GitHub never reveals them), move Windows, macOS and Arm jobs to self-hosted runners, and give `GITHUB_TOKEN` the `permissions:` it needs. ## Steps 1. **Bring the repository over.** On git.pkgforge.dev the server-side import from GitHub (**Settings → Imports → Import from GitHub**, or `githome migrate github acme/website --to acme/website`) needs the import container, which is not running, so it stops at its Git step; bring the code over with the local import (`githome migrate github acme/website --local`) or a plain Git push. Where the server-side import runs, the importer copies the history (workflow files included), issues, pull requests, branch protection, Actions variables, environments and the names of your secrets. The import starts no workflow runs; with the CI on, your first push does. See [Migrate from GitHub](https://git.pkgforge.dev/docs/migrate-from-github). 2. **Set your secret values.** The import lists every secret name, but never a value. A person who is a repository admin enters each one: **Set secret values** on the import's page, `githome secret set NPM_TOKEN -R acme/website`, or the REST API. Do this before your first push, because that push starts the workflows. See [Set secret values](https://git.pkgforge.dev/docs/migrate-from-github#set-secret-values). 3. **Check the workflow files.** Run `githome workflow validate .github/workflows/ci.yml` on each file. Errors fail the file; warnings name keys that are accepted but ignored. 4. **Fix `runs-on` where needed.** `ubuntu-*` labels run on hosted runners. Windows, macOS and Arm jobs need a self-hosted runner (see [Runners and runner sizes](#runners-and-runner-sizes)). 5. **Add `permissions:` where a job writes.** In repositories created on Githome, imported ones included, the job token can only read code and packages by default. A job that comments, labels, pushes, tags or publishes needs a `permissions:` block, for example `contents: write` or `pull-requests: write`, or an admin sets the repository default to write. See [Workflow permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions). 6. **Push a commit and watch the first runs** on the **Actions** tab, or with `githome run list` and `githome run watch ` (on a deployment with the CI on; on git.pkgforge.dev no run starts now). Fix what fails using the sections below. ## What runs unchanged - **Triggers:** `push`, `pull_request`, `pull_request_target`, `merge_group`, `workflow_dispatch`, `schedule`, `workflow_run`, `release`, `repository_dispatch` and `workflow_call`. See [Events that trigger workflows](https://git.pkgforge.dev/docs/actions/events). - **Workflow syntax:** expressions and contexts, matrices with `include` and `exclude`, `needs`, job outputs, `if` conditions, `concurrency`, job summaries, environment files and workflow commands. See [Workflow syntax](https://git.pkgforge.dev/docs/actions/workflow-syntax). - **Reusable workflows**, as long as they live on the same Githome instance and the calling job has no matrix. See [Reusable workflows](https://git.pkgforge.dev/docs/actions/reusable-workflows). - **Workflows in `.github/workflows/`.** Githome also reads `.githome/workflows/`, for workflows that should only run on Githome. ## Runners and runner sizes | `runs-on` | On Githome | | --- | --- | | `ubuntu-latest`, `ubuntu-24.04`, `ubuntu-22.04`, any other `ubuntu-*` label, `linux`, `x64` | A hosted Ubuntu 24.04 x64 container, fresh for each job | | `githome-tiny`, `githome-small`, `githome-medium`, `githome-large` | A hosted runner of that size | | `windows-*`, `macos-*` | Fails: there are no Windows or macOS hosted runners | | `ubuntu-24.04-arm` and other Arm labels | Runs on the same x64 image; there are no hosted Arm runners | | `[self-hosted, ...]` | A machine you connect with `githome runner`, matched on every label | A job without a size label gets the **large** size (4 vCPU, 12 GiB of memory, 20 GB of disk), unless its own earlier runs show that a smaller size serves it just as well. Add a label such as `runs-on: [ubuntu-latest, githome-small]` to pin a size. See [Runner sizes](https://git.pkgforge.dev/docs/actions/runners#runner-sizes). The hosted image is smaller than GitHub's. It has Git, Git LFS, curl, jq, build-essential, Python 3.12, Node.js 26 with npm, pnpm and yarn, Docker and `gh`. Go, Java, Ruby, Rust, .NET, PowerShell, browsers and cloud CLIs aren't preinstalled: install them with a setup action or `apt-get`. The apt package lists are removed, so run `apt-get update` before `apt-get install`. See [The Ubuntu 24.04 image](https://git.pkgforge.dev/docs/actions/runners#the-ubuntu-2404-image). **macOS, Windows, Arm and GPU jobs** run on a [self-hosted runner](https://git.pkgforge.dev/docs/actions/runners#self-hosted-runners): a repository admin creates a registration token, and you start `githome runner` on your machine with labels such as `--labels macos,arm64`. Jobs with `runs-on: [self-hosted, macos, arm64]` then go to it. On Windows, the documented route is to run the runner inside WSL 2. See [macOS, Windows and GPU machines](https://git.pkgforge.dev/docs/actions/runners#macos-windows-and-gpu-machines). ## Marketplace actions Any `uses: owner/repo@ref` is downloaded from GitHub when the step runs, so marketplace actions keep working. JavaScript actions (they run on the runner's own Node.js, 26 on a hosted runner), composite actions and Docker container actions are all supported. - `actions/checkout`, `actions/setup-node`, `actions/setup-python`, `actions/setup-go`, `actions/cache`, `actions/upload-artifact` and `actions/download-artifact` are built into the runner for speed, for the version ranges listed in [Built-in actions](https://git.pkgforge.dev/docs/actions/compatibility#built-in-actions). For other versions or inputs, the real action runs. - `actions/github-script` works with the REST API (`github.rest.*`); `github.graphql` doesn't, because the job token can't use Githome's GraphQL API yet. - Actions in **private GitHub repositories** can't be downloaded on hosted runners. Move them into a Githome repository and use them as local actions. See [Actions stored on Githome](https://git.pkgforge.dev/docs/actions/compatibility#actions-stored-on-githome). - `uses: acme/my-action@v1` always means the repository on GitHub, not on Githome. ## Secrets and variables - **Values come from people.** The importer copies repository variables with their values, and only the **names** of repository, environment and organization secrets. A repository admin who is a person sets each secret's value. Agents can't set secrets or variables anywhere. - **Where to set them:** repository secrets on **Settings → Secrets and variables** or with `githome secret set`; organization secrets with `githome secret set NAME --org acme`; environment secrets with the REST API. - **Pull request runs get secrets.** Every pull request comes from a branch of the same repository (there are no forks), so `pull_request` runs receive the repository's secrets. Runs of code an agent wrote don't, unless an admin allows it. See [Which runs receive secrets](https://git.pkgforge.dev/docs/actions/secrets-and-variables#which-runs-receive-secrets). - **Tools that encrypt secrets first** (GitHub's sealed-box `encrypted_value`) don't work: send the plain `value` over HTTPS; it's encrypted at rest. See [Secrets and variables](https://git.pkgforge.dev/docs/actions/secrets-and-variables). ## Caches and artifacts `actions/cache`, `actions/upload-artifact` and `actions/download-artifact` work as on GitHub, and the built-in versions share their storage and formats with the official actions. Caches are scoped per ref with the same fallbacks to the base branch and the default branch, each repository keeps up to 10 GB of caches, and artifacts are kept for up to 90 days. The `cache` input of the setup actions works too. See [Caching and artifacts](https://git.pkgforge.dev/docs/actions/caching-and-artifacts). ## Docker Job containers, service containers, Docker container actions, `docker build`, `docker run` and `docker compose` work on hosted runners, and so do `docker/setup-buildx-action`, `docker/login-action` and `docker/build-push-action`. The Docker daemon starts on first use, and Docker Hub images are pulled through the `mirror.gcr.io` mirror. If you publish images to `ghcr.io`, push them to the registry at `git.pkgforge.dev` instead, signed in with the job's `GITHUB_TOKEN` and `packages: write`. See [Docker in workflows](https://git.pkgforge.dev/docs/actions/docker) and [Migrating from ghcr.io](https://git.pkgforge.dev/docs/packages/container-registry#migrating-from-ghcrio). ## OIDC OIDC works with `permissions: id-token: write`, with `https://git.pkgforge.dev` as the issuer. In your cloud provider's trust policy, change the issuer host from `token.actions.githubusercontent.com` to `git.pkgforge.dev`, and keep your `sub` patterns unless they rely on a customized subject template. See [OpenID Connect (OIDC)](https://git.pkgforge.dev/docs/actions/oidc#differences-from-github). ## Environments The importer creates your environments with their deployment branch policies and variables, and lists their secret names. Then: - Set environment secrets with the REST API, as a repository admin who is a person. See [Environments and their secrets](https://git.pkgforge.dev/docs/migrate-from-github#environments-and-their-secrets). - Set required reviewers and wait timers again under **Settings → Environments**, with Githome people. They don't come across. See [Required reviewers and wait timers](https://git.pkgforge.dev/docs/actions/environments#required-reviewers-and-wait-timers). - Pull request runs never get environment secrets. Keep production credentials in an environment limited to protected branches. ## What doesn't work The full list, with error messages, is in [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). The differences you're most likely to meet: - No hosted Windows, macOS or Arm runners, no larger runners above 4 vCPU and no runner groups (`group` is ignored). - Events other than the ten listed above (`issues`, `issue_comment`, `pull_request_review` and the rest) parse but never start a run. - A matrix on a job that calls a reusable workflow isn't supported yet. - `github.graphql` in `actions/github-script` fails. - Problem matchers aren't supported, and annotations show in the job log only. - The `cmd` shell isn't supported, and hosted runners have no PowerShell. - Hard-coded `github.com` and `api.github.com` URLs point at GitHub: use `${{ github.server_url }}` and `${{ github.api_url }}`. ## Checklist 1. Import the repository (or push it) and read the import's warnings. 2. Set every secret value listed by the import, including environment and organization secrets. 3. Run `githome workflow validate` on every workflow file. 4. Replace `windows-*`, `macos-*` and Arm labels with `[self-hosted, ...]` labels and start a runner, or move the job to Linux. Check `matrix.os` values used in `runs-on`. 5. Add `apt-get update` before `apt-get install`, and install tools the hosted image doesn't have. 6. Add `permissions:` to jobs that write with `GITHUB_TOKEN`. 7. Move actions from private GitHub repositories into Githome and use them as local actions. 8. Replace `ghcr.io` with your instance's host (`git.pkgforge.dev` here), and hard-coded GitHub URLs with `github.server_url` and `github.api_url`. 9. Update OIDC trust policies to the `https://git.pkgforge.dev` issuer. 10. Set environment secrets, required reviewers and wait timers. 11. Check the required check names under **Settings → Branch protection** (they're ` / `, such as `CI / test`). 12. Push and watch the first runs. ## Frequently asked questions ### Do my GitHub Actions workflows run unchanged on Githome? Most do. Githome reads `.github/workflows/` and supports the same syntax, triggers, expressions, matrices, caches, artifacts, secrets, OIDC and Docker. Jobs that need Windows, macOS or Arm, actions from private GitHub repositories, or `github.graphql` need changes. See [Compatibility with GitHub Actions](https://git.pkgforge.dev/docs/actions/compatibility). ### Does Githome copy my GitHub secrets? It copies their names, never their values: GitHub doesn't reveal secret values, and the importer doesn't try. A repository admin who is a person sets each value on Githome, from the import's **Set secret values** page, the CLI or the API. ### Can I run macOS or Windows jobs on Githome? Not on hosted runners: they are Linux only. Run them on your own machine with a self-hosted runner (`githome runner`) and `runs-on: [self-hosted, ...]` labels. ### Do marketplace actions work on Githome? Yes. Githome downloads `uses: owner/repo@ref` actions from GitHub when the step runs. JavaScript, composite and Docker container actions are supported. Actions in private GitHub repositories can't be downloaded on hosted runners. --- # Make your CI faster on Githome > Speed up workflows on Githome Actions: runner sizes and auto-sizing, caching, setup and Docker head starts, matrices, and cancelling superseded runs, and the settings that decide each. Source: https://git.pkgforge.dev/docs/guides/faster-ci > **Note:** The forge CI of git.pkgforge.dev is dormant: githome reads and validates workflow files, but starts no run, so nothing here speeds up a run on that host now. What follows holds for workflow files and for a deployment that turns the CI on. On Githome with the CI on, a hosted job gets 4 vCPUs and 12 GiB of memory by default, and the common setup actions are built into the runner, so many workflows are fast without changes. To go further: let CPU-heavy jobs use all four cores, cache dependencies with keys that the default branch saves, use the Node.js and Python versions the image already has, split long jobs into parallel jobs with `needs` and matrices, and turn on cancelling of superseded pull request runs, which is off by default. Every job's log says how much CPU, memory and disk it used, so you can see where the time goes. ## Steps 1. **Read what a job used.** The last lines of each hosted job's log show its usage, for example `Resources: 0.1 of 4 vCPUs busy on average (0.3 at the 95th percentile), peak memory 0.3 GiB of 12.0 GiB, peak disk 1.6 GB of 19.3 GB`, and a line near the top names the runner size it got and why. The jobs API returns the same as `usage` and `runner_size`. 2. **Keep CPU-heavy jobs on the large size.** It's the default, and automatic sizing keeps builds and test suites there. Pin it with `runs-on: githome-large` if you want to be sure (see [How runner sizing works](#how-runner-sizing-works)). 3. **Cache dependencies** with the `cache` input of the setup actions or with `actions/cache`, keyed on your lock file (see [Caching](#caching)). 4. **Use the toolchains the image has**, and let Go, Java and Docker start early (see [Setup actions and head starts](#setup-actions-and-head-starts)). 5. **Run jobs in parallel.** Split a long job into jobs that `needs` only what they depend on, and spread tests over a matrix (see [Matrices and parallel jobs](#matrices-and-parallel-jobs)). 6. **Stop runs nobody will look at.** Add a `concurrency` group that cancels a pull request's older runs, and path filters for changes that don't need CI (see [Cancel superseded runs](#cancel-superseded-runs)). 7. **Re-run only what failed.** **Re-run failed jobs** on the run page (or `githome run rerun --failed`) runs the failed jobs and the jobs that depend on them, and keeps the rest from the earlier attempt without starting a runner. See [Re-run a run](https://git.pkgforge.dev/docs/actions/overview#re-run-a-run). ## How runner sizing works Hosted runners come in four sizes. Every size runs the same Ubuntu 24.04 image, so a job behaves the same on each. | Size | `runs-on` label | vCPU | Memory | Disk | | --- | --- | --- | --- | --- | | large (default) | `githome-large` | 4 | 12 GiB | 20 GB | | medium | `githome-medium` | 2 | 8 GiB | 16 GB | | small | `githome-small` | 1/2 | 4 GiB | 8 GB | | tiny | `githome-tiny` | 1/4 | 1 GiB | 4 GB | - **With a size label**, for example `runs-on: [ubuntu-latest, githome-small]`, the job gets that size (with several, the largest). - **Without one**, the job gets **large**, unless its own last runs (at least 3 of up to 5) all fit a smaller size with room to spare, including room for bursts onto several cores and for slower hosts. A job that ran out of memory, failed, timed out or got slower on a smaller size goes back to large for its next 20 runs, and re-runs always run on large. So a smaller size is never the reason a job fails or slows down twice. - **Smaller sizes are about cost, not speed.** A job that mostly waits (a deploy, API calls, polling) runs just as fast on a small machine and costs less. A job that computes is fastest on large. Large is the biggest hosted size; there are no larger runners. See [Runner sizes](https://git.pkgforge.dev/docs/actions/runners#runner-sizes) and [What hosted jobs cost](https://git.pkgforge.dev/docs/actions/runners#what-hosted-jobs-cost-and-keeping-it-low). ## Caching Githome's cache service works with the official `actions/cache` and with the built-in version, which downloads an archive in parallel ranges and extracts it while it arrives. The simplest cache is the `cache` input of a setup action: ```yaml - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm ``` `actions/setup-python` takes `cache: pip` or `pipenv`, and `actions/setup-go` caches by default. For anything else, use `actions/cache` with a key that changes when your lock file does: ```yaml - uses: actions/cache@v4 with: path: ~/.npm key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | npm-${{ runner.os }}- ``` Things that make caches hit more often: - **Let the default branch save caches.** A run reads entries saved on its own ref, then (for pull requests) the base branch, then the default branch. Entries saved on one feature branch are never visible to another. - **Include a hash of the lock file in the key.** Entries are immutable: a save with an existing key is skipped, so a key that never changes never refreshes. - **Use `save-always: true`** if failing jobs should still save, since the post step saves only after a successful job by default. - **Cache Docker layers** with `cache-from: type=gha` and `cache-to: type=gha` in `docker/build-push-action`, or with `type=registry` in the [container registry](https://git.pkgforge.dev/docs/packages/container-registry). `type=gha` in a plain `docker buildx build` step doesn't work, because `run:` steps don't get the cache service credentials. Each repository keeps up to 10 GB of caches, and entries no job restored for 7 days are deleted. See [Caching and artifacts](https://git.pkgforge.dev/docs/actions/caching-and-artifacts). ## Setup actions and head starts - **Node.js 26.7.0 and Python 3.12 are preinstalled.** When the version you ask `actions/setup-node` or `actions/setup-python` for is satisfied by them, the step uses them without a download. Any other version is downloaded each time. - **Go and Java start installing as the job begins.** When a job has `actions/setup-go` (v4 to v6) or `actions/setup-java` (v2 to v5, `distribution: temurin`, a major version such as `java-version: 21`), and the version is written in the workflow or comes from `matrix`, `inputs` or `vars`, the runner downloads that toolchain while checkout runs. Versions read from a file (`go-version-file`, `java-version-file`) and jobs that run in a `container:` install the usual way, as the step runs. - **Docker starts early for jobs that use it.** A job with `container:`, `services:`, a `docker://` action, or a step whose `uses:` or `run:` names `docker` gets the Docker daemon started in the background as the job begins. A `docker` command as the job's very first step waits for the daemon to finish starting. - **Other toolchains** (Ruby, Rust, .NET, browsers) aren't in the image and install as their step runs, so cache what they download. See [The Ubuntu 24.04 image](https://git.pkgforge.dev/docs/actions/runners#the-ubuntu-2404-image) and [Built-in actions](https://git.pkgforge.dev/docs/actions/compatibility#built-in-actions). ## Matrices and parallel jobs Jobs without `needs` between them run at the same time, each in its own container, and a job starts as soon as the jobs it needs have finished. A matrix turns one job into several: ```yaml jobs: test: runs-on: ubuntu-latest strategy: matrix: shard: [1, 2, 3, 4] steps: - uses: actions/checkout@v4 - run: npm ci - run: npm test -- --shard=${{ matrix.shard }}/4 ``` - An account runs up to 20 hosted jobs at once by default, across all its repositories; further jobs wait in line, oldest first. If a large matrix often waits, cap it with `strategy.max-parallel`. - A matrix may produce at most 256 jobs, and a run at most 1,000. - With `fail-fast` (the default), one failed leg cancels its unfinished siblings, so you hear about a failure sooner. See [strategy](https://git.pkgforge.dev/docs/actions/workflow-syntax#strategy) and [Limits](https://git.pkgforge.dev/docs/reference/limits). ## Cancel superseded runs As on GitHub, a new push to a pull request doesn't cancel the run for the commit before it. Githome doesn't turn this on for you, because cancelling can cut off a deploy halfway or turn an older commit's checks into "cancelled". To opt in for pull requests only, add this to the workflow: ```yaml concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} ``` Older runs of the same pull request are cancelled when a new commit arrives, and runs on your default branch finish. A run on a protected branch is only ever cancelled by runs on that same branch. See [Concurrency](https://git.pkgforge.dev/docs/actions/overview#concurrency). To skip runs entirely for changes that don't need them, use path filters on `push` and `pull_request`, for example `paths-ignore: ["docs/**", "**.md"]`. A job that doesn't run reports no check, and a required check that never reports shows as `required check '' has not run`, so be careful with path filters on workflows whose checks are required. See [Path filters](https://git.pkgforge.dev/docs/actions/events#path-filters) and [Status checks](https://git.pkgforge.dev/docs/actions/overview#status-checks-on-commits-and-pull-requests). ## Frequently asked questions ### What hardware do Githome's hosted runners have? By default, 4 vCPUs, 12 GiB of memory and 20 GB of disk, running Ubuntu 24.04 on x64 in a fresh container for each job. Smaller sizes (2, 1/2 and 1/4 vCPU) are picked per job from its own measured runs, or with a `githome-*` label. ### Does Githome cancel superseded workflow runs automatically? No. As on GitHub, older runs keep running unless the workflow has a `concurrency` group with `cancel-in-progress`. Add one with `cancel-in-progress: ${{ github.event_name == 'pull_request' }}` to cancel older pull request runs and leave default-branch runs alone. ### Can I get a runner bigger than 4 vCPUs? Not as a hosted runner: large (4 vCPU, 12 GiB) is the biggest size. For bigger machines, GPUs or long-lived caches, connect your own machine as a [self-hosted runner](https://git.pkgforge.dev/docs/actions/runners#self-hosted-runners). ### Why did my job get a smaller runner? Its last runs all fit a smaller size with room to spare, so Githome picked it to save cost. The log's `Runner size:` line says which runs it was based on. If a smaller size ever makes the job fail or slower, it goes back to large for its next 20 runs. Pin `runs-on: githome-large` to keep it on large. --- # Automate versions and releases with release-please > Run release-please on Githome with the release-please action or its CLI: the workflow, the permissions and setting it needs, CI on release pull requests, and troubleshooting. Source: https://git.pkgforge.dev/docs/guides/release-please > **Note:** The forge CI of git.pkgforge.dev is dormant, so the workflow below starts no run there now. The CLI route (see below) runs from your own terminal and does not need the forge CI. [release-please](https://github.com/googleapis/release-please) reads your Conventional Commits, keeps a release pull request open with the next version and changelog, and creates the tag and release when you merge it. It works on Githome as it does on GitHub: the `googleapis/release-please-action@v4` action runs unchanged, and the `release-please` CLI works with Githome's API URLs. Githome answers the GraphQL queries release-please sends (commit history with each commit's pull request, merged pull requests and releases) and the REST calls it makes (files, git data, pull requests, labels, tags and releases). ## Steps 1. **Keep your release-please files.** `release-please-config.json` and `.release-please-manifest.json` (or the action's `release-type` input) work as they are. An imported repository already has them. 2. **Let workflows open pull requests.** Open the repository's **Settings → Actions** tab, check **Allow GitHub Actions to create and approve pull requests** under **Workflow permissions**, and click **Save**. This needs the admin role. It's off by default, as on GitHub, and without it the action fails with `GitHub Actions is not permitted to create pull requests.` See [GITHUB_TOKEN permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions#creating-and-approving-pull-requests). 3. **Add the workflow.** The same file as on GitHub: ```yaml # .github/workflows/release-please.yml on: push: branches: [main] permissions: contents: write # tags and releases pull-requests: write # the release pull request issues: write # its labels jobs: release-please: runs-on: ubuntu-latest outputs: release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.tag_name }} steps: - uses: googleapis/release-please-action@v4 id: release with: release-type: node # or leave it out and keep release-please-config.json ``` The action's `github-api-url`, `github-graphql-url` and `changelog-host` inputs default to `${{ github.api_url }}`, `${{ github.graphql_url }}` and `${{ github.server_url }}`, which point at Githome, so you don't set them. Changelog links point at your repository on Githome. 4. **Build and ship from the release.** Later jobs read the outputs, as on GitHub, for example to build and upload a mobile app only when a release was created: ```yaml ship: needs: release-please if: ${{ needs.release-please.outputs.release_created == 'true' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: ./scripts/ship.sh "${{ needs.release-please.outputs.tag_name }}" ``` 5. **Merge the release pull request** when you want to release. Squash, merge commit and rebase merges all work. The next run of the workflow tags the merge, creates the release and relabels the pull request `autorelease: tagged`. ## CI on the release pull request As on GitHub, what a job's `GITHUB_TOKEN` does starts no new workflow runs, so a release pull request opened with it gets no `pull_request` runs. If your branch protection requires checks, give the action a token of its own: a [personal or agent token](https://git.pkgforge.dev/docs/accounts/tokens) with the `write` scope, stored as a secret. ```yaml - uses: googleapis/release-please-action@v4 with: token: ${{ secrets.RELEASE_PLEASE_TOKEN }} ``` Pull requests and pushes made with that token start workflows like anyone else's. If it's an [agent's](https://git.pkgforge.dev/docs/guides/ai-agent-with-guardrails) token, the agent rules apply: it opens and updates the release pull request, and a person merges it. ## The CLI Run release-please from a terminal or another CI system with Githome's REST and GraphQL URLs. `--graphql-url` is the address without `/graphql` (release-please adds it): ```sh export GITHOME_TOKEN=ghome_... # a token with the write scope npx release-please release-pr --repo-url acme/app --token "$GITHOME_TOKEN" \ --api-url https://git.pkgforge.dev/api/v3 --graphql-url https://git.pkgforge.dev/api npx release-please github-release --repo-url acme/app --token "$GITHOME_TOKEN" \ --api-url https://git.pkgforge.dev/api/v3 --graphql-url https://git.pkgforge.dev/api ``` `--target-branch` picks another branch than the default one. For changelog links that point at Githome when you use the CLI, add `"changelog-host": "https://git.pkgforge.dev"` to `release-please-config.json`; the action sets it for you. ## Troubleshooting | Message | Fix | | --- | --- | | `GitHub Actions is not permitted to create pull requests.` | Check **Allow GitHub Actions to create and approve pull requests** (step 2), or use a token of its own. | | `Resource not accessible by integration (the workflow's GITHUB_TOKEN needs permissions: ...)` | Add the `permissions:` from step 3 to the workflow or job. | | `release-please failed: Error updating ref heads/release-please--branches--...` (the API answered ``refusing to allow a GitHub App to create or update workflow `...` without `workflows` permission``) | A workflow file changed on the base branch while the release pull request was open. Rebuilding the release branch on the new base would change workflow files on it, which a job's `GITHUB_TOKEN` may never do on Githome. Merge or close the release pull request and delete its branch (the next run opens a fresh one), or give the action a [token of its own](#ci-on-the-release-pull-request). | | `Could not find commits for branch - it likely does not exist.` | The branch in `target-branch` (or the default branch) doesn't exist, or the token can't read the repository. | | Changelog links go to github.com | Set `changelog-host` (CLI), or check that the action's `changelog-host` input isn't set to GitHub. | | `No commits for path: ., skipping` | Nothing since the last release follows Conventional Commits (`feat:`, `fix:`, `feat!:` and so on), so there's nothing to release. | ## Related - [Releases](https://git.pkgforge.dev/docs/collaboration/releases): tags, drafts, notes and assets. - [GraphQL API](https://git.pkgforge.dev/docs/reference/graphql-api): the queries Githome answers. - [Move your GitHub Actions workflows to Githome](https://git.pkgforge.dev/docs/guides/move-github-actions-workflows). --- # Give an AI coding agent its own account, with guardrails > Create an agent account for Claude Code, Codex or any MCP client on Githome, connect it, and let the server keep a person in charge of protected branches, merges and secrets. Source: https://git.pkgforge.dev/docs/guides/ai-agent-with-guardrails On Githome, an AI coding agent gets an account of its own, separate from yours: you create it under **Settings → Agents**, give it a token (or let Claude Code or Codex sign in as it through the browser), and its commits, pull requests and comments show as the agent's, on your behalf. The server holds it to guardrails whatever tool it uses: it can't push to or merge into the default branch or protected branches, its pull requests need a person's approval, its own approvals and check results never count, and runs of the code it writes get none of your repository or organization secrets. Repository admins relax these rules, per branch or per repository, when you're ready, for example to let its pull requests merge by themselves once CI passes and a person approves. ## Steps 1. **Create the agent.** Go to **Settings → Agents**, enter an **Agent username** (for example `review-bot`), choose the **Owner** (you, or an organization where you're an owner or admin) and keep the **Maximum role** at **Write**. Click **Create agent**. Only people can create agents, and an organization's agent can reach only that organization's repositories. 2. **Create a token for it**, unless the agent will sign in through the browser (step 4). In the agent's row, open **Create a token for review-bot**, keep the **Scope** at **Write**, choose the **Days** (1 to 366), and click **Create token**. Copy it: it's shown once. Give it to the agent as an environment variable such as `GITHOME_TOKEN`, never in a file you commit. See [Tokens for agents](https://git.pkgforge.dev/docs/agents/overview#tokens-for-agents). 3. **Protect the default branch.** Under the repository's **Settings → Branch protection**, add a rule for `main` with **Require a pull request before merging**, at least one **Required approvals**, and your CI checks under **Required status checks**. Agents can't push to the default branch either way; the rule makes sure every change is reviewed and tested. See [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection). 4. **Connect the agent** (see [Connect Claude Code, Codex or another MCP client](#connect-claude-code-codex-or-another-mcp-client)). 5. **Tell it how to work**, for example in your agent instructions file: work on a new branch, open a pull request with an `intent` that states the goal, wait for checks with `githome pr checks --watch`, and fix failures before asking for review. 6. **Review and merge its pull requests**, by hand or with merge on green (see [Review and merge agent pull requests](#review-and-merge-agent-pull-requests)). ## What the server enforces These rules hold for Git pushes, the REST API, MCP tools and sandboxes alike, whatever the agent's role: | Rule | What it means | | --- | --- | | Never more access than its owner | Its role is the lowest of its maximum role (write by default), its owner's role on the repository and its token's scope. | | No pushes to the default branch or protected branches | Pushes and commits there fail with `agents may not push to protected or default branches; open a pull request`. It pushes other branches freely. | | No merges into the default branch or protected branches | The merge blocker reads `agents may not merge into this branch; a human must merge`. | | A person approves its pull requests | At least one approval from a person, even on a branch with no rule. An agent's approval never counts; its requested changes still block. | | Its check results don't count | Commit statuses and check runs an agent reports never satisfy a required check, so it can't mark its own work as passing. | | No secrets for runs of its code | A workflow run whose code came from an agent gets no repository or organization secrets, only its job token, and its token is held to the same rules. Environment secrets reach it only from environments limited to protected branches, and never on pull request refs. | | No settings that guard the repository | It can't change branch protection, secrets, variables or environments, dismiss reviews, delete or transfer repositories, or create other agents. | | No push protection bypass | A push or commit containing something that looks like a credential is always refused. | | Stamped commits | Commits Githome writes for it carry a `githome-agent review-bot on-behalf-of diffy` header. | The full table, with how to relax each rule, is in [Guardrails](https://git.pkgforge.dev/docs/agents/overview#guardrails). ## Connect Claude Code, Codex or another MCP client Every app connects to the same MCP server, `https://git.pkgforge.dev/mcp`. Apps with browser sign-in need no token: on Githome's consent page, choose to **act as** your agent, and Write access. - **Claude Code:** install the CLI and run `githome setup`, then run `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`. In Claude Code, run `/mcp`, select **githome**, choose **Authenticate**, and pick the agent on the consent page. See [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code). - **Codex:** run `githome setup`, then `codex mcp add githome --url https://git.pkgforge.dev/mcp` and `codex mcp login githome`, and pick the agent on the consent page. See [Codex](https://git.pkgforge.dev/docs/connect/codex). - **Cursor, VS Code and other MCP apps:** add `https://git.pkgforge.dev/mcp` as a remote HTTP server and sign in. See [Other apps](https://git.pkgforge.dev/docs/connect/other-apps). - **Headless (CI, scripts, scheduled jobs):** send the agent's token instead. For Claude Code: ```sh claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp \ --header 'Authorization: Bearer ${GITHOME_TOKEN}' ``` `githome mcp-config` prints a snippet for other clients. See [Headless use](https://git.pkgforge.dev/docs/connect/how-sign-in-works#headless-use). - **Git and the CLI:** with `GITHOME_TOKEN` set, `githome auth setup-git` lets Git push with it, and `githome auth setup-gh` makes `gh pr create` and `gh pr checks` work against Githome. See [GitHub CLI](https://git.pkgforge.dev/docs/agents/github-cli). Ask the agent "Who am I on Githome?" to check: the `whoami` tool answers with the agent's login. **Cloud environments.** For a Claude Code cloud environment, or any other agent sandbox, open the repository's **Settings → Agent setup** and choose **Generate agent token**. It makes an agent that can reach only that repository and gives you the allowed domain, a one-line setup script and the environment variables to paste. A **Check** turns green once a session has set itself up. See [Cloud agent environments](https://git.pkgforge.dev/docs/connect/cloud-agents). ## Review and merge agent pull requests - **Find what needs you.** [Today](https://git.pkgforge.dev/docs/agents/today), the first page after signing in, lists **Agent PR needs a person's approval** for agent pull requests no person has approved at their latest commit. - **Read the intent first.** Every pull request can carry an `intent`, one or two sentences on what the change is meant to do, shown at the top so you can check the diff against it. See [Pull requests](https://git.pkgforge.dev/docs/collaboration/pull-requests). - **Approve, then merge.** You (or anyone with write access other than the agent) approve. The agent's owner can approve, because the owner is a different account from the agent. - **Let it merge on green.** An admin opens the repository's **Settings → Merge on green**, ticks the checks that must pass and the agents, and chooses whether agents' pull requests merge **Once the checks pass and a person approved** or **As soon as the checks pass**. Each agent pull request then merges by itself when its conditions are met. See [Merge on green automatically](https://git.pkgforge.dev/docs/collaboration/merge-on-green). - **Or allow auto-merge per branch.** **Allow agents to land pull requests through auto-merge** on a branch's rule (with at least one required check) lets the agent turn on auto-merge for its own pull requests (`enable_auto_merge` over MCP, or `githome pr merge --auto`). Githome merges once every rule is met; if the agent pushes again, a person approves again. See [Agents landing changes](https://git.pkgforge.dev/docs/repositories/branch-protection#agents-landing-changes). - **Workflow changes always need a person.** A pull request that adds, changes or deletes a workflow file never lands through an agent's auto-merge: CI can't vouch for a change to itself. - **Plan for deploys after agent merges.** The forge CI of git.pkgforge.dev is dormant, so no workflow runs there now; where CI runs, a merge that auto-merge makes for an agent is the agent's push, so later runs on that branch are runs of agent code and get no repository or organization secrets. Keep deploy credentials in an environment limited to protected branches, or have an admin turn on **Give runs of agent code the repository's and organization's secrets**. See [Which runs receive secrets](https://git.pkgforge.dev/docs/actions/secrets-and-variables#which-runs-receive-secrets). Agent review and agent tasks run in a sandbox, which is dormant on git.pkgforge.dev; their pages are [Agent review](https://git.pkgforge.dev/docs/agents/review) and [Agent tasks](https://git.pkgforge.dev/docs/agents/tasks). ## Audit what agents did - **On every item:** agents have an `agent` badge and `on behalf of ` next to their name on pull requests, reviews, comments and workflow runs, and the API returns `"type": "Bot"` for them. - **In Git:** commits Githome writes for an agent carry the `githome-agent ... on-behalf-of ...` header, covered by the commit's SHA. See it with `git cat-file -p `. - **Its tokens:** **Settings → Agents** lists each agent's tokens with their scope and last use, and a **revoke** link. Githome sends a security email when an agent or an agent token is created, where the deployment's email sending is set up. - **The audit log:** the superadmin sees every audited action on the page **Audit log** of the dash, with the agent as the actor and its owner alongside (`review-bot for diffy`). See [Audit log](https://git.pkgforge.dev/docs/security/audit-log). - **Cut it off:** revoke one token to stop one running copy, or **Disable** the agent under **Settings → Agents** to revoke all its tokens at once. ## Frequently asked questions ### Can an AI agent push to main on Githome? Not by default. Agents can't push to the default branch or to any protected branch; they push a branch and open a pull request. A repository admin can allow it on a branch's protection rule with **Allow agents to push directly**. ### Can an agent approve or merge its own pull request? An agent's approval never counts toward required approvals, and agents can't merge into the default branch or protected branches. A person approves its pull request. A repository admin can let agents land approved pull requests through auto-merge, so CI and a person decide rather than the agent, or waive the approval so green required checks are enough. ### Can an agent read my repository secrets? Agents can't create, change or delete secrets, and a workflow run of code an agent wrote gets no repository or organization secrets unless a repository admin turns that on. Environment secrets reach such a run only from environments limited to protected branches, and never on pull request refs. Agents with write access can read Actions variables, which aren't secret. ### Which AI coding agents work with Githome? Any agent that uses Git, the GitHub CLI, the REST API or MCP. There are guides for [Claude](https://git.pkgforge.dev/docs/connect/claude), [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code), [Codex](https://git.pkgforge.dev/docs/connect/codex), Cursor and VS Code ([Other apps](https://git.pkgforge.dev/docs/connect/other-apps)). ### How do I take away an agent's access? Revoke its token under **Settings → Agents**, or click **Disable** next to the agent to revoke all its tokens at once. An app connected through the browser is disconnected under **Settings → Access tokens → Connected apps**. --- # Connect AI apps > Add Githome to Claude, Claude Code, Codex or any MCP app with one URL and a browser sign-in. Pick your app and follow its guide. Source: https://git.pkgforge.dev/docs/connect Githome works with AI apps through its [MCP server](https://git.pkgforge.dev/docs/agents/mcp). Every app connects to the same address: ```text https://git.pkgforge.dev/mcp ``` There is no token to copy. The app sends you to Githome in your browser, you choose whom it acts as and what it may do, and it's connected. You can see and disconnect every app under **Settings → Access tokens → Connected apps**, which also shows this URL with a copy button. ![Settings → Access tokens on Githome: the MCP server URL with a Copy button, links to the guides for Claude, Claude Code, Codex and other apps, and two connected apps, Claude Code and Codex, each acting as the agent ada-bot with write access.](https://git.pkgforge.dev/docs/images/connected-apps.webp) ## Pick your app | You use | What you do | Guide | | --- | --- | --- | | **Claude** on claude.ai, Claude Desktop or the Claude mobile apps | Add a custom connector with the URL, then approve it on Githome. | [Claude](https://git.pkgforge.dev/docs/connect/claude) | | **Claude Code** | Run `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp`, then sign in from `/mcp`. | [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code) | | **Codex** (OpenAI's coding agent) | Run `codex mcp add githome --url https://git.pkgforge.dev/mcp`, then `codex mcp login githome`. | [Codex](https://git.pkgforge.dev/docs/connect/codex) | | **Cursor, VS Code or another MCP app** | Add the URL as a remote (HTTP) MCP server. | [Other apps](https://git.pkgforge.dev/docs/connect/other-apps) | | **Claude Code cloud environments** and other agent sandboxes | Paste three boxes from the repository's **Settings → Agent setup**. | [Cloud agent environments](https://git.pkgforge.dev/docs/connect/cloud-agents) | | **CI, scripts** (no browser) | Send an agent's token instead of signing in. | [Headless use](https://git.pkgforge.dev/docs/connect/how-sign-in-works#headless-use) | ## What a connected app can do Once connected, the app works with Githome the way you would, within the access you gave it: - Read code, branches and commits, compare branches, and commit files to a new branch without git. - Open pull requests with an [intent](https://git.pkgforge.dev/docs/collaboration/pull-requests), comment, review, merge, or turn on auto-merge. - Follow CI where a deployment runs it: list workflow runs, read the log of a failing job, and re-run or cancel runs. The forge CI of git.pkgforge.dev is dormant, so no workflow runs there now. - File and update issues, and draft and publish releases. - Search and read these docs. The [MCP tool reference](https://git.pkgforge.dev/docs/reference/mcp-tools) lists every tool. In a terminal, Claude Code and Codex can also use git and the [`githome` CLI](https://git.pkgforge.dev/docs/reference/cli). ## You stay in control - **Act as an agent.** On the consent page you pick whether the app acts as you or as one of your [agents](https://git.pkgforge.dev/docs/agents/overview). An agent is the safer choice for an AI app: its commits and comments are marked as the agent's, it can't push to protected or default branches, and its pull requests need a person's approval unless a branch rule says otherwise. - **Choose the access.** Read, Write or Admin. Write is enough for pull requests, reviews and issues. Admin is never preselected. - **Disconnect any time.** **Settings → Access tokens → Connected apps** lists every app with whom it acts as, its access and when it was last used. **Disconnect** ends it at once. How the sign-in works, and what each part of the consent page means, is in [How sign-in works](https://git.pkgforge.dev/docs/connect/how-sign-in-works). ## For AI agents reading this page If you are an agent setting yourself up: - Running in a terminal with a person nearby: ask them to add the server for your app ([Claude Code](https://git.pkgforge.dev/docs/connect/claude-code), [Codex](https://git.pkgforge.dev/docs/connect/codex)) and approve the sign-in. Don't try to complete a browser sign-in yourself. - Running in a cloud sandbox for one repository: `githome setup --repo /` sets up git and gh and checks them; the person sets up the sandbox from the repository's **Settings → Agent setup** ([Cloud agent environments](https://git.pkgforge.dev/docs/connect/cloud-agents)). - Running headless with `GITHOME_TOKEN` set: add the server with an `Authorization: Bearer ${GITHOME_TOKEN}` header, as in [Headless use](https://git.pkgforge.dev/docs/connect/how-sign-in-works#headless-use). `githome mcp-config` prints the snippet. - Either way, `githome auth setup-git` lets git push with the same sign-in, and `githome auth setup-gh` makes `gh` work against git.pkgforge.dev ([GitHub CLI](https://git.pkgforge.dev/docs/agents/github-cli)). --- # Claude > Add Githome to claude.ai, Claude Desktop and the Claude mobile apps as a custom connector, approve it on Githome, and use it in chats and Projects. Source: https://git.pkgforge.dev/docs/connect/claude Add Githome to Claude once as a custom connector, and Claude can read your repositories, open and review pull requests and file issues from any chat. The connector works on claude.ai, in Claude Desktop and in the Claude mobile apps. You need a Githome account and a Claude plan that allows custom connectors. For Claude Code in a terminal, see [Claude Code](https://git.pkgforge.dev/docs/connect/claude-code) instead. ## Add the connector 1. On [claude.ai](https://claude.ai) or in Claude Desktop, open **Settings → Connectors** and choose **Add custom connector**. 2. Fill in the two fields and choose **Add**: | Field | Value | | --- | --- | | Name | `Githome` | | Remote MCP server URL | `https://git.pkgforge.dev/mcp` | Leave **Advanced settings** (OAuth client ID and secret) empty: Claude registers itself with Githome. 3. Choose **Connect** next to Githome. A Githome tab opens. Sign in with your passkey if you aren't signed in. 4. On the consent page, choose whom Claude acts as and its access, then choose **Connect**. The tab returns to Claude and the connector shows as connected. > [!TIP] > Pick one of your [agents](https://git.pkgforge.dev/docs/agents/overview) under **Act as** and **Write** access. Claude can then open pull requests and comment as that agent, and its pull requests wait for a person's approval like any agent's. > [!NOTE] > On a Team or Enterprise plan, an owner adds the connector once for the organization (in Claude's organization settings, under **Connectors**). Each member then chooses **Connect** and approves it with their own Githome account, so everyone's Claude acts with their own permissions. A person needs an account on git.pkgforge.dev first: the superadmin sends each invitation link by hand. ## Use it in a chat Open the tools menu below the message box and make sure **Githome** is turned on. Then ask in plain words, for example: - "List my open pull requests on Githome and tell me which ones are waiting on a review." - "What changed on the main branch of acme/widgets since last week?" - "Open an issue in acme/widgets: the login page doesn't load on Safari." - "Review pull request 42 in acme/widgets and comment on anything risky." Claude asks before it uses a tool that changes something, unless you allowed that tool to run without asking. The connector also works in Claude Projects, and in Claude Desktop and the mobile apps once you've added it on claude.ai or in Desktop. ## Check that it works - In Claude, **Settings → Connectors** shows Githome as connected. - On Githome, **Settings → Access tokens → Connected apps** lists **Claude**, with whom it acts as and its access. - Ask Claude "Who am I on Githome?". It calls the `whoami` tool and answers with the account you picked. ## Disconnect On Githome, choose **Disconnect** next to Claude under **Settings → Access tokens → Connected apps**. Its tokens stop working at once. To remove the connector from Claude too, remove it under **Settings → Connectors**. ## Troubleshooting | Problem | What to do | | --- | --- | | The Githome tab says "Can't connect this app" | Claude's registration expired (registrations nobody used are removed after a week), or it asked to return somewhere it didn't register. Remove the connector in Claude and add it again. | | Claude says a tool needs the write scope | You connected with **Read** access. Disconnect Claude on Githome and connect again with **Write**. | | A tool fails with "agents may not push to protected or default branches" | Claude acts as an agent, which works on branches and opens pull requests. Ask it to open a pull request instead. | | Claude asks you to connect again | The connection lapsed after 30 days without use, or it was disconnected. Choose **Connect** again. | | Some tool calls fail with "Error POSTing to endpoint: Bad Gateway" | The call failed before it got an answer from Githome. Asking Claude to try again usually gets through. If it keeps failing, report it in the public tracker at [github.com/Azathothas/issues](https://github.com/Azathothas/issues) with the label `git.pkgforge.dev`. | More detail on the consent page and what the tokens can do: [How sign-in works](https://git.pkgforge.dev/docs/connect/how-sign-in-works). --- # Claude Code > Add Githome's MCP server to Claude Code with one command, sign in from /mcp, and let Claude push branches and open pull requests on Githome. Source: https://git.pkgforge.dev/docs/connect/claude-code Claude Code connects to Githome through its MCP server at `https://git.pkgforge.dev/mcp`. Together with the `githome` CLI, Claude can then push a branch, open a pull request and merge it, without leaving the terminal. Githome ships no Claude Code plugin: the MCP server is the whole connection. ## 1. Install the CLI The CLI gives Claude git access and the pull request commands. It needs Node.js 26 or later, and installs a private copy of the Node.js 26 LTS when the machine has none: ```sh curl -fsSL https://git.pkgforge.dev/install | bash githome setup ``` On Windows, in PowerShell: `powershell -c "irm https://git.pkgforge.dev/install.ps1 | iex"`, then `githome setup`. It opens your browser to sign in (on a machine without one it shows a code to enter instead), runs `githome auth setup-git` so git pushes and pulls with the same sign-in, and signs in `gh` when you have it. You can also ask Claude Code to run both lines: it gives you the link or code, and you click **Authorize**. See [Install and sign in to the CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in). ## 2. Add the MCP server ```sh claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp ``` With `--scope user` the server is available in every project on your machine. Leave the flag out to keep it to the current project. To share it with everyone working on a repository, commit it in the repository's `.mcp.json`; each person signs in with their own account: ```json { "mcpServers": { "githome": { "type": "http", "url": "https://git.pkgforge.dev/mcp" } } } ``` ## 3. Sign in 1. In Claude Code, run `/mcp`, select **githome** and choose **Authenticate**. 2. Your browser opens Githome's consent page. Choose whom Claude Code acts as and its access, then choose **Connect**. 3. Back in the terminal, `/mcp` shows the server as connected. ![Githome's consent page for Claude Code: "Connect Claude Code to Githome", an app published by claude.ai that sends you back to an app on this computer, with Act as set to the agent ada-bot and Write access selected, and the Connect and Cancel buttons.](https://git.pkgforge.dev/docs/images/consent-claude-code.webp) On a machine without a browser, run `claude mcp login githome --no-browser`, open the printed link on any device, and paste the address you land on back into the terminal. > [!TIP] > Act as one of your [agents](https://git.pkgforge.dev/docs/agents/overview). Claude Code's commits, comments and pull requests then show as the agent's, and they wait for a person's approval before they land. ## Check that it works ```sh claude mcp list ``` `githome` shows **Connected** (before you sign in it shows **Needs authentication**). Then try it: ```sh claude -p "Who am I on Githome?" ``` The `whoami` tool answers with the account you picked on the consent page. ## Pull requests from the terminal With the CLI installed, Claude Code works through the usual loop on its own: ```sh git push -u origin my-branch githome pr create --title "Fix the login redirect" --intent "Sign-in should return people to the page they came from" githome pr merge --auto --squash ``` The pull request commands use the current branch's pull request when you leave out the number. `githome pr checks --watch` waits for a branch's checks and `githome run logs ` reads the log of a failed job, on a deployment where CI runs; the forge CI of git.pkgforge.dev is dormant, so no workflow runs there now. To let Claude use `gh` as it would on GitHub, and to see the branch's pull request in Claude Code's footer and the desktop app, sign gh in to Githome once. `githome setup` in step 1 did this if gh was installed then; otherwise run: ```sh githome auth setup-gh ``` See [GitHub CLI](https://git.pkgforge.dev/docs/agents/github-cli) for what works with `gh`. ## Headless: CI and cloud sessions Where nobody can approve a browser sign-in, give Claude Code an [agent's token](https://git.pkgforge.dev/docs/agents/overview) in `GITHOME_TOKEN` and add a server that sends it: ```sh claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp \ --header 'Authorization: Bearer ${GITHOME_TOKEN}' ``` Keep the single quotes: Claude Code reads `${GITHOME_TOKEN}` from the environment each time it connects, so the token is never written to its settings. A token and the browser sign-in can't share one server entry: with the header set, Claude Code doesn't fall back to OAuth. The CLI and `githome auth setup-git` read `GITHOME_TOKEN` too. For Claude Code on the web, set up the environment from the repository's [Agent setup](https://git.pkgforge.dev/docs/connect/cloud-agents). More in [Headless use](https://git.pkgforge.dev/docs/connect/how-sign-in-works#headless-use). ## Troubleshooting | Problem | What to do | | --- | --- | | `claude mcp list` doesn't show `githome` | Run the `claude mcp add` command of step 2 again. A server added without `--scope user` belongs to the project you ran it in. | | `/mcp` shows the server as needing authentication | Choose **Authenticate**, or run `claude mcp login githome`. | | The browser says "Can't connect this app" | Remove the server with `claude mcp remove githome` and add it again, then sign in. | | A tool says it needs the write scope | You connected with **Read**. Disconnect Claude Code under **Settings → Access tokens → Connected apps** and sign in again with **Write**. | | `git push` to `main` fails with "agents may not push to protected or default branches" | Claude Code acts as an agent: push a branch and open a pull request. | | `/mcp` shows the server but every call answers `401` | The server entry has an `Authorization` header with an old or empty `GITHOME_TOKEN`. Set the variable to a current token, or remove the header to use the browser sign-in. | --- # Codex > Add Githome's MCP server to OpenAI's Codex with codex mcp add, sign in with codex mcp login, and let Codex work with pull requests and issues on Githome. Source: https://git.pkgforge.dev/docs/connect/codex Codex, OpenAI's coding agent, connects to Githome through its MCP server at `https://git.pkgforge.dev/mcp`. Together with the `githome` CLI, Codex can push a branch, open a pull request and merge it. Githome ships no Codex plugin: the MCP server is the whole connection. ## 1. Install the CLI ```sh curl -fsSL https://git.pkgforge.dev/install | bash githome setup ``` On Windows, in PowerShell: `powershell -c "irm https://git.pkgforge.dev/install.ps1 | iex"`, then `githome setup`. The CLI needs Node.js 26 or later, and installs a private copy of the Node.js 26 LTS when the machine has none. `githome setup` signs you in through your browser, lets git use the sign-in (as `githome auth setup-git` does) and signs in `gh` when you have it. The CLI gives Codex git access and the pull request commands. See [Install and sign in to the CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in). ## 2. Add the MCP server ```sh codex mcp add githome --url https://git.pkgforge.dev/mcp ``` or in `~/.codex/config.toml`: ```toml [mcp_servers.githome] url = "https://git.pkgforge.dev/mcp" ``` ## 3. Sign in ```sh codex mcp login githome ``` Codex opens Githome's consent page in your browser. Choose whom Codex acts as and its access, then choose **Connect**. ![Githome's consent page for Codex: "Connect Codex to Githome", an app published by chatgpt.com that sends you back to an app on this computer, with Act as set to the agent ada-bot and Write access selected.](https://git.pkgforge.dev/docs/images/consent-codex.webp) Without a browser on the machine, add `--no-browser`: Codex prints the link, you open it on any device, and paste the address you land on back into the terminal. > [!TIP] > Act as one of your [agents](https://git.pkgforge.dev/docs/agents/overview), so Codex's commits and pull requests are marked as the agent's and wait for a person's approval. ## Check that it works ```sh codex mcp list ``` The `githome` server shows **OAuth** under **Auth** (before you sign in it says **Not logged in**). Then ask Codex: "Who am I on Githome?" ## Pull requests With the CLI installed, Codex pushes a branch, opens a pull request with `githome pr create --intent ...` and lands it with `githome pr merge --auto --squash`. On a deployment where CI runs, it waits with `githome pr checks --watch` and reads failures with `githome run logs `; the forge CI of git.pkgforge.dev is dormant, so no workflow runs there now. For `gh`, run `githome auth setup-gh` once; see [GitHub CLI](https://git.pkgforge.dev/docs/agents/github-cli). ## Headless: CI and cloud sessions Give Codex an [agent's token](https://git.pkgforge.dev/docs/agents/overview) in `GITHOME_TOKEN` and point the server at it: ```sh codex mcp add githome --url https://git.pkgforge.dev/mcp --bearer-token-env-var GITHOME_TOKEN ``` or, for one run without changing `config.toml`: ```sh codex -c 'mcp_servers.githome.url="https://git.pkgforge.dev/mcp"' \ -c 'mcp_servers.githome.bearer_token_env_var="GITHOME_TOKEN"' exec "..." ``` `codex mcp list` then shows **Bearer token** under **Auth**. More in [Headless use](https://git.pkgforge.dev/docs/connect/how-sign-in-works#headless-use). ## Troubleshooting | Problem | What to do | | --- | --- | | `codex mcp list` says **Not logged in** | Run `codex mcp login githome`. | | The browser says "Can't connect this app" | Run `codex mcp logout githome`, then `codex mcp login githome` again. | | A tool says it needs the write scope | You connected with **Read**. Disconnect Codex under **Settings → Access tokens → Connected apps** and sign in again with **Write**. | | `codex mcp list` shows **Bearer token** but calls answer `401` | The `GITHOME_TOKEN` variable is unset, expired or revoked. Set it to a current token, or remove the server and add it again without `--bearer-token-env-var` to use the browser sign-in. | --- # Cloud agent environments > Set up a Claude Code cloud environment, or any other agent sandbox, for a Githome repository by pasting three boxes from Settings → Agent setup. git, gh and the CLI then work from the first session. Source: https://git.pkgforge.dev/docs/connect/cloud-agents A cloud agent runs in a sandbox that starts fresh: a Claude Code cloud environment, Codex in the cloud, or any other agent platform. **Settings → Agent setup** on a repository gives it everything it needs to work on that repository from its first session, with no manual wiring: - a token that reaches **only that repository**, - the domain to allow, - a one-line setup script hosted on Githome, - the environment variables, with the token filled in, - and a **Check** that turns green once a session has set itself up and passed a self-test. Then the agent can clone, push branches, open pull requests and use `gh` against the repository. The page is the same for every agent platform: each one asks for the same three things. ## Before you start - You need write access to the repository. Admins find **Agent setup** among the repository's settings; people with write access get a **Settings** tab that opens it. - Generating a token needs a passkey sign-in from the last 2 hours, as for any token. If yours is older, Githome asks you to confirm with your passkey first. ## Set up a Claude Code cloud environment 1. Open the repository on Githome, then **Settings → Agent setup** (`https://git.pkgforge.dev///settings/agent-setup`). 2. Choose **Generate agent token**. Change the label if you like, so you can tell environments apart later. The token appears once, already filled into box 4. 3. In Claude Code, open the environment selector under the message box at [claude.ai/code](https://claude.ai/code), and edit the environment (the settings icon on its row) or add a new one. The **Edit cloud environment** dialog has the three fields to fill. 4. **Network access**: choose **Custom**, put `git.pkgforge.dev` under **Allowed domains**, and keep **Also include default list of common package managers** ticked. **Full** works too. The default **Trusted** level doesn't include git.pkgforge.dev. 5. **Setup script**: paste box 3, which looks like this: ```sh curl -fsSL https://git.pkgforge.dev///agent-setup.sh | bash ``` 6. **Environment variables**: paste box 4 as it is: ```text GITHOME_TOKEN=ghome_… GH_ENTERPRISE_TOKEN=ghome_… GH_HOST=git.pkgforge.dev GITHOME_REPO=/ ``` 7. Save, and start a session in the environment. Back on the Agent setup page, the **Check** turns green within seconds of the setup script finishing (the page updates by itself). In the session, the repository is cloned at `/home/user/`, and these all work with no prompt and no path prefix: ```sh githome --version githome whoami git clone https://git.pkgforge.dev//.git gh api user --hostname git.pkgforge.dev --jq .login gh pr list --state all # inside the clone ``` > [!NOTE] > Claude Code runs the setup script once and keeps a snapshot of the machine for later sessions, for about seven days or until you change the script or the allowed domains. So a later session's clone can be behind: ask Claude to `git pull` first. A new token needs no new snapshot: the token is read from the environment each time, never from disk. ## Other agent platforms Every agent sandbox has the same three settings under its own names: | Box | What it is | Where it goes | | --- | --- | --- | | Network | `git.pkgforge.dev` | The sandbox's allowed domains or internet access setting. | | Setup script | `curl -fsSL https://git.pkgforge.dev///agent-setup.sh \| bash` | A setup, install or startup command that runs before the agent starts. It needs bash, curl and git, and Node.js 26 or later (it downloads the Node.js 26 LTS from nodejs.org when there isn't one, so allow that domain too in that case). | | Environment variables | The lines in box 4 | The sandbox's environment variables or secrets that are passed to commands. | On a machine you already work on, you don't need any of this: install the CLI and run `githome setup` ([Install and sign in to the CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in)). Workflows get their own token automatically on a deployment where CI runs ([Workflow permissions](https://git.pkgforge.dev/docs/actions/workflow-permissions)); the forge CI of git.pkgforge.dev is dormant. ## What the setup script does The script is the same for everyone, with the repository's name in it, and holds no secret: open its URL (box 3 of the page) in a browser and read it before you use it. It runs these steps, in order: 1. Installs the `githome` CLI and puts it on PATH (`/usr/local/bin/githome` when it runs as root, as in Claude Code). It skips the download when the installed CLI is already the server's current build, so later runs take a few seconds. 2. Stops with a clear message if `GITHOME_TOKEN` isn't set, after setting up what it can: git is then ready to use the token as soon as it is in the environment. 3. Runs `githome setup --repo /`, which: - makes git use the token for git.pkgforge.dev (`githome auth setup-git`): git asks the CLI, which reads `GITHOME_TOKEN` from the environment each time. The token is never written to disk, so no snapshot or file holds it. - leaves `gh` to `GH_ENTERPRISE_TOKEN` and `GH_HOST` from the environment. Without them it signs `gh` in with `GITHOME_TOKEN` instead (`gh` then keeps it in its own config). - clones the repository unless it's there already, or fetches it when it is. It goes in `/home/user/` in a Claude Code cloud environment and in the current directory elsewhere; set `GITHOME_CLONE_DIR` to choose, or `GITHOME_NO_CLONE=1` to skip it. - checks each part and prints one line per check, saying what to change when one fails. - reports the result to the repository's **Check**. It is fully non-interactive, never prints the token, and is safe to run at the start of every session. It exits with 1 when the CLI can't be installed or a check fails, so a broken setup isn't kept in a snapshot and the session's setup log shows why. ## The token Each person gets their own agent for each repository the first time they generate a token there: an agent account named after the repository, such as `zutrix-agent`. Its commits, comments and pull requests show as the agent's, acting for you. | Setting | What it is | | --- | --- | | Repository | This repository only. The agent, and every token it has, gets no access to any other repository or to account or organization settings, even public ones. | | Code | Read and write. It pushes branches; protected branches and the default branch take pull requests instead. | | Pull requests and issues | Read and write: open, comment, review (advisory), update. | | Workflows and logs | Read, re-run and cancel. No access to secrets or variables. | | Merge | On by default. See below. | | Most it can do | Write, and never more than you can do: if you lose access, so does the agent. | | Expiry | 90 days. **Renew** gives the same token another 90 days, so nothing needs pasting again. | | Label | Shown in the token list and in the audit log. | ### Merging With **Can merge pull requests** on (the default), the agent may merge a pull request, or turn on auto-merge for it, once: - a person has approved the pull request's **latest commit**: agents' own reviews never count, and a push after the approval needs a new one; - every rule of the branch is met: required approvals, required checks, linear history, the merge queue; - the pull request doesn't change a workflow file (`.github/workflows/` or `.githome/workflows/`): those always need a person to merge, because CI can't vouch for a change to itself. Turn it off on the page and the agent can't merge into the default branch or a protected one at all; a person merges. Rules on the branch itself still apply either way, such as **Allow agents to land pull requests through auto-merge** in [Branch protection](https://git.pkgforge.dev/docs/repositories/branch-protection). **Merge its pull requests on green** (offered under **Label** when you generate the first token, and next to **Can merge pull requests** afterwards) has Githome turn on auto-merge for each pull request the agent opens, so it lands by itself once the default branch's required checks pass: right away where the repository waives the approval through [Merge on green](https://git.pkgforge.dev/docs/collaboration/merge-on-green), otherwise once a person approved its latest commit. The text under the box says which applies in this repository. It needs at least one required check on the branch, and a workflow change still needs a person. ### Renew, revoke and regenerate - **Renew** keeps a token working for 90 days from today. - **Revoke and regenerate** stops the token at once and makes a new one, filled into box 4 for you to paste. Use it whenever a token may have leaked. - **Revoke** stops it. - Admins of the repository see everyone's agents for it on the page and can turn any of them off, which revokes their tokens. Every token change is in the audit log (`agent_setup.token.create`, `.regenerate`, `.renew`, `.revoke`), and a security email about a created token is sent only where the deployment's email sending is set up. ## Keep the token safe - Environment variables are visible to anyone who uses the environment, so treat the token as shared with them. - Never paste the token into a chat or a screenshot. If it leaks, choose **Revoke and regenerate**. - Claude Code's **Network secrets** keep a credential outside the session, but they don't reach setup scripts, and `gh` won't run without a token of its own, so Agent setup uses environment variables. ## When the Check fails The page shows each failed line with what to change. The usual ones: | Line | What to do | | --- | --- | | `server: can't reach git.pkgforge.dev` | Allow `git.pkgforge.dev` in the environment's network settings (Custom with git.pkgforge.dev, or Full). | | `GITHOME_TOKEN: not set` | Add the Environment variables lines from the page. | | `GITHOME_TOKEN: refused (revoked or expired)` | **Revoke and regenerate** (or generate a new token), then paste the new token in both places. | | `repository: the token can't see /` | Use a token from this repository's Agent setup page: each token reaches only its own repository. | | `GH_HOST: not set` | Add `GH_HOST=git.pkgforge.dev` to the environment variables. | | `gh: GH_ENTERPRISE_TOKEN isn't the same token as GITHOME_TOKEN` | Paste the same token into both. | | `clone: … exists and isn't a clone of …` | Move that directory, or set `GITHOME_CLONE_DIR`. | Until a session runs the script with every check passing, the Check says **Not connected yet**. To check again inside a running session, run the setup script again, or `githome setup --repo /`. ## For AI agents reading this page If you are an agent in a sandbox with `GITHOME_TOKEN` set: - `githome setup --repo /` checks your setup and fixes what it can; each failed line says what the person has to change in the environment's settings. Don't try to change those settings yourself. - If `GITHOME_TOKEN` isn't set, ask the person to open the repository's **Settings → Agent setup** on Githome and paste its boxes into your environment's settings. - Open pull requests with `githome pr create --intent` or `gh pr create`. You may merge only what a person approved; see [Merging](#merging). - The [REST API](https://git.pkgforge.dev/docs/api) reports the Check at `GET /api/v3/repos///githome/agent-setup`. --- # Other apps > Connect Cursor, VS Code or any other MCP client to Githome with the server URL and a browser sign-in, or with a token where sign-in isn't supported. Source: https://git.pkgforge.dev/docs/connect/other-apps Any app that supports remote MCP servers over HTTP can connect to Githome. Apps that support MCP's OAuth sign-in need only the URL; the rest send a token. ```text https://git.pkgforge.dev/mcp ``` ## Cursor Add Githome to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` in a project to share it with everyone who opens the project: ```json { "mcpServers": { "githome": { "url": "https://git.pkgforge.dev/mcp" } } } ``` Cursor lists the server in its MCP settings with a way to sign in; Githome's consent page opens in your browser. To clone Githome repositories in Cursor, use the plain HTTPS clone URL of the repository. Githome ships no editor extension. ## VS Code Add Githome to `.vscode/mcp.json` in a workspace (or run **MCP: Add Server** from the Command Palette and choose **HTTP**): ```json { "servers": { "githome": { "type": "http", "url": "https://git.pkgforge.dev/mcp" } } } ``` Start the server from the file or the MCP view, and sign in when VS Code asks. To clone Githome repositories in VS Code, use **Git: Clone** with the repository's plain HTTPS clone URL, and run `githome auth setup-git` once so git pushes with your Githome sign-in. Githome ships no editor extension. ## Any other app Look for "remote MCP server", "HTTP" or "Streamable HTTP" in the app's settings, and give it `https://git.pkgforge.dev/mcp`. If the app supports OAuth for MCP, it finds everything else on its own: Githome answers its first request with a `401` that points at the sign-in details, the app registers itself, and you approve it on the consent page. See [How sign-in works](https://git.pkgforge.dev/docs/connect/how-sign-in-works). ## Apps without OAuth sign-in Send a Githome token in the `Authorization` header instead. Use an [agent](https://git.pkgforge.dev/docs/agents/overview)'s token (created under **Settings → Agents**) and keep it in an environment variable, never in a file you commit: ```json { "mcpServers": { "githome": { "url": "https://git.pkgforge.dev/mcp", "headers": { "Authorization": "Bearer ${GITHOME_TOKEN}" } } } } ``` `githome mcp-config` prints this snippet. Apps that can only start local (stdio) servers, such as those set up through Claude Desktop's configuration file, can reach Githome through a small bridge; [MCP server](https://git.pkgforge.dev/docs/agents/mcp#claude-desktop-and-other-clients-that-start-local-servers) has the setup for those and for many more clients. ## Check that it works Ask the app "Who am I on Githome?". It calls the `whoami` tool and answers with the account it acts as. Apps that signed in also show under **Settings → Access tokens → Connected apps** on Githome. --- # How sign-in works > How AI apps sign in to Githome's MCP server with OAuth 2.1, what the consent page asks, Connected apps, tokens, and headless use with an agent token. Source: https://git.pkgforge.dev/docs/connect/how-sign-in-works Githome follows the [MCP authorization spec](https://modelcontextprotocol.io/specification/draft/basic/authorization) (OAuth 2.1), so any MCP app that supports it can connect with nothing but the URL, not only Claude and Codex. ## The steps 1. The app calls `https://git.pkgforge.dev/mcp` without a token and gets `401` with `WWW-Authenticate: Bearer resource_metadata="https://git.pkgforge.dev/.well-known/oauth-protected-resource/mcp"`. 2. It reads that document and the authorization server's at `/.well-known/oauth-authorization-server`. 3. It identifies itself: by the URL of its own client metadata document (Claude Code uses `https://claude.ai/oauth/claude-code-client-metadata`, Codex `https://chatgpt.com/oauth/codex/client.json`), or by registering at `/oauth/register` (RFC 7591), as claude.ai and most other apps do. 4. It sends you to `/oauth/authorize` with a PKCE challenge, and you approve it on [the consent page](#the-consent-page). 5. Githome sends your browser back to the address the app registered with a one-time code, which only works together with the PKCE secret the app kept. The app trades it at `/oauth/token` for an access token and a refresh token. | | | | --- | --- | | Access token | An ordinary Githome token (`ghome_…`) for the account you picked, with the access you picked. It lasts 8 hours and works everywhere a token does (MCP, the REST API, git), with every permission check and branch rule that applies to that account. | | Refresh token | `ghomefr_…`. Each use returns a new one and retires the old. A connection that isn't used for 30 days lapses. A retired refresh token used again later is taken as stolen and ends the connection. | | Redirect addresses | `https` anywhere, `http` only on your own computer (`localhost`, `127.0.0.1`), or an app's own scheme such as `cursor://`. Loopback addresses may use any port. | | Endpoints | `/.well-known/oauth-protected-resource/mcp`, `/.well-known/oauth-authorization-server`, `/oauth/register`, `/oauth/authorize`, `/oauth/token`, `/oauth/revoke` (RFC 7009). | | Grants | Authorization code with PKCE (S256 only), and refresh tokens. No implicit, password or client credentials grants. | ## The consent page ![Githome's consent page for Claude Code: the app's name, "An app published by claude.ai", where it sends you back, the Act as choice between yourself and your agents, Read, Write and Admin access, and the Connect and Cancel buttons.](https://git.pkgforge.dev/docs/images/consent-claude-code.webp) The page names the app and where it will send you back. An app identified by a client metadata document shows the site that publishes it ("An app published by claude.ai"); an app that registered itself shows the name it chose, marked as not checked by Githome. Only connect an app you are setting up yourself at that moment. - **Act as:** yourself, or one of your agents (yours, or an organization's you own or administer). Acting as an agent is a good default for an AI app: its commits and comments show as the agent's, on your behalf, and its pull requests need a person's approval, so nothing it does lands unreviewed. - **Access:** Read, Write (preselected when the app asks for more) or Admin. Admin is never preselected. Approving needs a passkey sign-in from the last 2 hours, as creating a token does. ## Connected apps **Settings → Access tokens → Connected apps** lists every app you connected: its name, where it sends you back, whom it acts as, its access, and when it was last used. **Disconnect** ends the connection and its tokens at once. Each approval is its own connection, so the same app on two computers shows twice. Connections and disconnections are in the [audit log](https://git.pkgforge.dev/docs/security/audit-log) as `oauth.connect` and `oauth.disconnect`. ## Headless use Where nobody can open a browser (CI jobs, cloud agent sessions, scheduled tasks), give the app a token instead: an [agent](https://git.pkgforge.dev/docs/agents/overview)'s token is best, created under **Settings → Agents**. Put it in `GITHOME_TOKEN`, never in a file you commit. | App | Setup | | --- | --- | | Claude Code | `claude mcp add --scope user --transport http githome https://git.pkgforge.dev/mcp --header 'Authorization: Bearer ${GITHOME_TOKEN}'`, or `"headers": { "Authorization": "Bearer ${GITHOME_TOKEN}" }` in `.mcp.json`. | | Codex | `codex mcp add githome --url https://git.pkgforge.dev/mcp --bearer-token-env-var GITHOME_TOKEN`, or `bearer_token_env_var = "GITHOME_TOKEN"` under `[mcp_servers.githome]`. | | Other apps | An `Authorization: Bearer ...` header; see [Other apps](https://git.pkgforge.dev/docs/connect/other-apps#apps-without-oauth-sign-in). | | git, gh and the CLI | The CLI reads `GITHOME_TOKEN`. Run `githome auth setup-git` once so git uses it too, and `githome auth setup-gh` for gh. | | Claude Code on the web and other cloud sessions | Allow `git.pkgforge.dev` in the environment's network settings, add `GITHOME_TOKEN` as an environment secret, and clone over HTTPS. | A token and the browser sign-in can't share one server entry: with the header set, neither Claude Code nor Codex falls back to OAuth. `githome mcp-config` prints the snippet for your token. ## Troubleshooting | Symptom | Cause and fix | | --- | --- | | The browser says "Can't connect this app" | The app's registration expired (registrations nobody used are removed after a week), or it asked to send you back to an address it didn't register. Remove the server or connector and add it again. | | An app that worked asks you to sign in again | The connection lapsed after 30 days unused, or it was disconnected (by you, or after a reused refresh token). Sign in again. | | Tools fail with `this token needs the write scope` | You connected with Read access. Disconnect it under Connected apps and connect again with Write. | | A tool fails with `agents may not push to protected or default branches` | The app acts as an agent. It should work on a branch and open a pull request; see [What agents can and can't do](https://git.pkgforge.dev/docs/agents/overview). | --- # Passkeys and sign-in > How people sign in to Githome with passkeys, join from an invite, manage passkeys and browser sessions, and recover a lost passkey with a sign-in link. Source: https://git.pkgforge.dev/docs/accounts/passkeys-and-sign-in People sign in to Githome in the browser with a passkey (WebAuthn). There are no passwords. This page covers signing in, joining from an invite, adding and removing passkeys, managing signed-in browsers, the security emails you get, and how to get back in when you lose a passkey. Passkeys are only for the web UI. Git, the `githome` CLI, scripts and MCP clients use personal access tokens instead (see [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens)); the CLI gets its own when you approve `githome login` in the browser (see [Install and sign in to the CLI](https://git.pkgforge.dev/docs/accounts/cli-sign-in)). For your username, display name, profile picture and light or dark theme, see [Profile and preferences](https://git.pkgforge.dev/docs/accounts/profile-and-preferences). ## How passkey sign-in works A passkey is a key pair that your device, browser or password manager creates for `git.pkgforge.dev`. Githome stores only the public key. When you sign in, your device proves it holds the private key after you unlock it with your fingerprint, face, PIN or screen lock. Details that matter in practice: | Behaviour | Value | | --- | --- | | Where a passkey works | Only on the host it was created for (the hostname of the instance, `git.pkgforge.dev`). A passkey for one Githome instance does not work on another. | | Kind of passkey | Discoverable credentials (resident keys). You don't type a username: the browser offers the passkeys it holds for the site. | | User verification | Required. The device must unlock the passkey with a biometric, PIN or screen lock, not just a tap. | | Attestation | None requested. Githome accepts any authenticator that can create a discoverable, user-verifying passkey. | | Time to complete the browser prompt | 2 minutes. The sign-in attempt itself expires after 5 minutes. | | Browser session length | 30 days, extended by another 30 days on each day you use it, up to 90 days after you signed in. | Githome is invite-only, and open sign-up is off on git.pkgforge.dev. You can't create an account from the sign-in page: new people create their first passkey from an invite link (see [Join from an invite](#join-from-an-invite)). Anyone can browse and clone public repositories without an account. ## Sign in 1. Open `https://git.pkgforge.dev/login`, or any page that needs you to be signed in. Githome redirects you to the sign-in page and back to that page afterwards. 2. Click **Sign in with a passkey**. 3. Your browser shows its passkey prompt. Pick the passkey for your Githome account, or choose to use a phone or a security key if the browser offers it. 4. Unlock the passkey with your fingerprint, face, PIN or screen lock. You land on the page you were trying to open (or your dashboard). To sign out, click **Sign out** in the header; that ends this browser's session only. The sign-in page also says how to recover a lost passkey: "Ask an administrator for a sign-in link". The administrator is the superadmin. ## Join from an invite The superadmin makes an instance invite in the dash and sends you its link, like `https://git.pkgforge.dev/invite/#proof=`. Githome sends no email for it. Opening the whole link shows a **Join Githome** page: 1. Check the **Username** field. It is filled in from the part of your email address before the `@`; change it if you like. Usernames start with a letter or digit and use letters, digits, `-` and `_`, up to 39 characters. Some names are reserved (for example `api`, `settings`, `login`, `admin`, `docs`). 2. Optionally fill in a **Display name** (up to 100 characters). 3. Click **Create a passkey and join**, and complete your browser's passkey prompt. Githome creates your account, saves the passkey, signs you in and shows "Welcome to Githome, . You can sign in with this passkey from now on." You land on your dashboard. Where the deployment sends email, you also get a welcome email. Creating the account accepts every open invite sent to your email address. If the email address already has an account, the invite page asks you to sign in with that account's passkey first; after that the same page shows an **Accept invite** button. See [Invitations](https://git.pkgforge.dev/docs/accounts/invitations) for how invites are created, how long they last and what each kind grants. An invite of an organization or a repository goes to a person who has an account, and makes no account. Opening one whose address has no account answers `403` with **Ask for an invitation**. ## Open sign-up The code of Githome has a setting for open sign-up, where anyone can create an account at `/signup` with a code sent to their email address. The setting is off on git.pkgforge.dev: `/signup` answers `404` (or leads to `/early-access` where Turnstile is set), the sign-in page has no **Create an account** link, and accounts come from invites. Ask the superadmin for an invitation link. ## Manage your passkeys Go to **Settings → Passkeys and sessions** (`/settings/security`). The **Passkeys** box lists every passkey on your account with: - its name, - a **synced** badge when the passkey is backed up by your password manager or platform (so it syncs to your other devices), or **this device only** when it is stored on a single device or security key, - when it was added and when it was last used to sign in (or "never used to sign in"). ### Add a passkey Add a passkey on each device you use, or keep one in a password manager that syncs, so losing one device doesn't lock you out. 1. On the device or browser you want to add, sign in and open **Settings → Passkeys and sessions**. 2. Under **Add a passkey**, optionally type a name (up to 100 characters). If you leave it empty, Githome names it after the device and browser, for example `Mac · Safari` or `Android · Chrome`. 3. Click **Add a passkey** and complete the browser prompt. You see "Passkey "" added." and, where the deployment sends email, Githome sends you a "A passkey was added to your account" email. If the browser says "This device already has a passkey for this account.", the authenticator you picked already holds a Githome passkey for you. Pick a different one (another device, a phone or a security key). ### Remove a passkey Click **Remove** next to the passkey and confirm. Removing a passkey also signs out every other browser that signed in with it, which is what you want for a lost or stolen device. The browser you are using stays signed in. Where the deployment sends email, Githome sends you a "A passkey was removed from your account" email. You can't remove your last passkey. The list shows **Only passkey** instead of a **Remove** button, and the server refuses with "Add another passkey before removing your last one." Add a new passkey first, then remove the old one. Passkeys can only be managed from a signed-in browser. An API request made with an access token gets "Sign in with your passkey first." ## Confirming it's you Adding or removing a passkey, creating a token or an agent, changing your username, deleting or transferring a repository or organization, exporting or deleting your account, need a sign-in from the last 2 hours. If you signed in earlier, Githome shows **Confirm it's you**. Use your passkey, and you go back to the page you were on. Then do the action again. See [Security overview](https://git.pkgforge.dev/docs/security/overview#confirming-its-you). ## Sessions and signing out other browsers Each successful sign-in creates a browser session, stored in an HTTP-only, secure cookie (`__Host-ghome_session`) that only `git.pkgforge.dev` can read. A session lasts 30 days and is extended by another 30 days on each day you use it, so a browser you use regularly stays signed in. However often you use it, a session ends 90 days after you signed in, and you sign in with your passkey again. The **Signed-in browsers** box on **Settings → Passkeys and sessions** lists your active sessions (up to 100), newest activity first. Each row shows the device and browser, a **this browser** badge for the one you are using, when it signed in, how (a passkey or a sign-in link) and when it was last active. To end one session, click **Sign out** on its row and confirm. You see "Signed out of that browser." To end every session except the current one, click **Sign out everywhere else** and confirm "Sign out every other browser?". You see "Signed out of every other browser." Those browsers need a passkey to sign in again. When the superadmin disables your account, every browser session ends at once, and signing in again is refused with "Your account is disabled." until the account is enabled. Signing out other browsers does not revoke access tokens. If you think someone has your token, revoke it under **Settings → Access tokens** (see [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens#revoke-a-token)). ## Security emails about sign-in Where the deployment sends email, these emails always send; you can't turn them off in notification settings. | Email | When it is sent | | --- | --- | | New sign-in to your account | You sign in with a passkey from a browser and passkey combination Githome hasn't seen for your account before. It shows when, the device, the location (city and country) and the IP address. | | A passkey was added to your account | You add a passkey in settings, or with a sign-in link from an administrator. | | A passkey was removed from your account | You remove a passkey. | | Welcome to Githome | You create your account from an invite. | | Your one-time sign-in link | Not sent: the superadmin sends you the sign-in link of the dash. | A browser is identified by the passkey used plus its operating system and browser name (for example `Mac · Chrome`). Signing in again from the same browser with the same passkey doesn't send another email. The device you joined or added a passkey from counts as known. If you get one of these emails and it wasn't you: open **Settings → Passkeys and sessions**, click **Sign out everywhere else**, remove any passkey you don't recognize, revoke any token you don't recognize under **Settings → Access tokens**, and tell the superadmin. See [Notifications](https://git.pkgforge.dev/docs/accounts/notifications) for every email Githome sends. ## Recover your account If you have lost every passkey (or the device that held your only passkey), ask the superadmin for a sign-in link. There is no email recovery. The link lets you add a new passkey to your existing account; your repositories, tokens and settings are untouched. Recovering your account signs out every other browser signed in to it, in case the device you lost is one of them. Only browser sessions end: your access tokens keep working, so scripts and Git keep running. If you think someone has a token, revoke it under **Settings → Access tokens** once you are back in. The page you land on says "Every other browser signed in to your account was signed out; your access tokens keep working.", and the audit log records it as `session.revoke_others`. ### Sign-in link from an administrator The superadmin can create a one-time sign-in link for you in the dash: 1. The superadmin opens the page **People** of the dash and clicks **Sign-in link** next to you (see [Site administration](https://git.pkgforge.dev/docs/admin/site-administration#sign-in-links)). 2. The superadmin sends you the link through a channel you trust. githome sends no email for it. 3. Open the link (`https://git.pkgforge.dev/signin#`). The **Add a passkey** page names the account it belongs to. 4. Optionally enter a **Name for this passkey**, click **Create a passkey** and complete the browser prompt. You are signed in and taken to **Settings → Passkeys and sessions** with "Passkey "" added. Use it to sign in from now on." Every other browser signed in to your account is signed out. | Sign-in link rule | Value | | --- | --- | | Lifetime | 24 hours from when it was created | | Uses | Once. After that, or after it expires, it shows "this sign-in link is invalid, already used, or expired". | | Accounts | People only, and not disabled accounts | | What it does | Adds a passkey to the account, signs that browser in and signs every other browser out. It doesn't remove your other passkeys or revoke your access tokens. | Anyone with the link can add a passkey to your account, so don't forward it. After you are back in, remove the passkey of the device you lost. ### No email recovery git.pkgforge.dev has no recovery by email and no Cloudflare Access sign-in: `/auth/access` answers `404` with "Account recovery by email is not set up on this instance. Ask an administrator for a sign-in link." The sign-in link of the superadmin is the way back in. ## Browser and device requirements - A browser with WebAuthn passkey support, such as a current version of Chrome, Safari, Edge or Firefox. In a browser without it, the sign-in button shows "This browser does not support passkeys. Try a current version of Chrome, Safari, Edge or Firefox." - JavaScript turned on. Without it the page shows "Passkeys need JavaScript." - An authenticator that can store a discoverable passkey and verify you: a phone or computer with a fingerprint reader, face unlock, PIN or screen lock, a password manager that supports passkeys, or a hardware security key that stores passkeys and has a PIN or biometric. - The real site address. Passkeys are bound to `git.pkgforge.dev`, so they don't work through another hostname or a raw IP address. ## Password managers and synced passkeys Passkeys saved in a password manager or your platform's keychain usually sync to your other devices, so one passkey covers your laptop and phone. Githome shows these with the **synced** badge. A passkey on a hardware security key or in a device-only store shows **this device only**; keep a second passkey somewhere else so you can't be locked out by losing that one key. If your browser offers several places to save the passkey when you create it, pick the password manager or keychain you use on all your devices. ## How Githome sign-in differs from GitHub - Githome has no passwords and no username-and-password sign-in, so there is no password reset and no separate two-factor setup: the passkey's user verification is the second factor. - You can't sign up from the sign-in page: accounts come from invites, and open sign-up is off. - Account recovery is a one-time link from the superadmin. There is no email recovery and there are no recovery codes. - Git over HTTPS and the API never accept a passkey or browser session; they take a personal access token, much like GitHub. ## Troubleshooting | Message or symptom | What it means and what to do | | --- | --- | | "The passkey prompt was closed or timed out. Try again when you are ready." | The browser prompt was cancelled, or 2 minutes passed. Click the button again. If no passkey is offered at all, this device has no passkey for Githome: use another device, or recover your account. | | "This passkey is not registered with Githome. It may have been removed." | The passkey you picked was removed from your account (or belongs to another instance). Pick another passkey or recover your account. You can also delete the stale passkey from your device or password manager. | | "This sign-in attempt expired. Please try again." | More than 5 minutes passed since the attempt started, or the browser didn't send the sign-in cookie back (for example, blocked cookies). Reload the page and try again. | | "Passkey check failed: ..." | The browser's response didn't verify, for example because the page was opened on a different hostname. Open `https://git.pkgforge.dev/login` directly and try again. | | "Your account is disabled." | The superadmin disabled your account. Ask them to enable it. | | "This device already has a passkey for this account." | When adding a passkey: pick a different authenticator. | | "This browser does not support passkeys..." | Update your browser or use another one. | | "this invite is invalid, already used, or expired" | Ask the person who invited you for a new invite. | | "this sign-in link is invalid, already used, or expired" | Sign-in links work once within 24 hours. Ask the superadmin for a new one. | | "Waiting for an invite" page | Your account waits for the superadmin. This page doesn't arise on git.pkgforge.dev, where accounts are made from an invite; elsewhere, ask the superadmin to invite that address, or click **Request access**. | | Lost every passkey | Ask the superadmin for a [sign-in link](#sign-in-link-from-an-administrator). | | `git` or the CLI asks for a password | Use a personal access token, not a passkey. See [Personal access tokens](https://git.pkgforge.dev/docs/accounts/tokens). | --- # 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. Source: https://git.pkgforge.dev/docs/accounts/invitations 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/#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/`) 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](https://git.pkgforge.dev/docs/accounts/tokens) for Git, the CLI and agents. ## Who can invite | Who | What they can invite to | Where | | --- | --- | --- | | The superadmin, in the dash | The instance (no organization or repository) | The page **People** of the dash | | Organization owners | Their organization, as member, admin or owner | The organization's **People** tab (**Add people**), `githome invite --org`, the API | | Organization admins | Their organization, as member or admin | The 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 admin | The 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 works once, until