githome

module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2026 License: Apache-2.0

README

Githome

Githome is a self-hosted software forge that speaks GitHub. The goal is narrow and uncompromising: an unmodified gh, an unmodified git, and any client that talks to the GitHub REST or GraphQL API should work against a Githome server the same way they work against github.com, byte for byte where it matters.

That means the compatibility target is not "GitHub-like". It is GitHub:

  • REST API v3 under /api/v3, with the same JSON shapes, the same error envelopes, the same headers (Link pagination, ETag, the rate-limit family, X-GitHub-Request-Id, X-GitHub-Api-Version).
  • GraphQL API v4 under /api/graphql, with a schema that matches field for field, Relay-style connections, and the node/databaseId/id triple.
  • The gh CLI, unmodified, pointed at a Githome host through GH_HOST. If a flow works on github.com it works here, including --json field selection and --paginate.
  • Git transport over smart-HTTP, so git clone and git push go straight to the server.
  • A built-in web UI, served from the same binary and on by default: repo and code browsing, Markdown with syntax highlighting, issues, pull requests with the diff, inline code review, search, profiles, and settings. It is a reimplemented Primer look, server-rendered, and the write paths work with JavaScript disabled.

Status

Usable today, and honest about the edges. The compatibility surface is built and released: four tagged versions are out, and one tag push produces the prebuilt binaries, the Linux packages, and the container image attached to each release (see Install).

Version What it added
v0.1.0 The first complete forge: auth, git read and push, issues, pull requests, code review, webhooks, events, search, conditional requests, the full REST and GraphQL surface
v0.1.1 A performance pass: batch loaders instead of N+1, keyset pagination, FTS-backed search, object caches, GraphQL dataloaders
v0.1.2 The release pipeline: archives, deb/rpm/apk, a multi-arch container image, and the language-agnostic package managers
v0.1.3 The built-in web UI (repo and code browsing, diffs, inline review, profiles, settings, notifications), a conformance suite wired into CI, the REST and GraphQL compatibility ladders, h2c serving, and a green Postgres test leg

What works, end to end:

  • Authentication. Classic PATs with a prefix and checksum, the OAuth device and web flows, scopes on every response header, only the token hash stored.
  • Repositories and git. gh repo operations, git clone, git fetch, and git push over smart-HTTP, with a post-receive sync that keeps the database consistent with what git wrote.
  • Issues, pull requests, and code review. The full lifecycle over REST and GraphQL, async mergeable state, squash/merge/rebase, inline review threads, commit statuses, check runs, reviewDecision, and statusCheckRollup.
  • Webhooks and the Events API, with X-Hub-Signature-256 delivery, an SSRF guard, and at-least-once retry.
  • Search, pagination, and conditional requests, with FTS-backed search, RFC 5988 Link headers, and ETag/If-None-Match that returns 304 without spending rate limit.
  • The web UI described above.

Not yet:

  • SSH git transport (the config is reserved, the server is not wired)
  • Organization accounts (everything is user-owned for now)
  • At-rest encryption of webhook secrets
  • GitHub Actions runner compatibility (in progress in the separate tamnd/githome-action project, not yet served by this binary)

The definition of done is mechanical, not a claim. Every endpoint has a recorded fixture and a contract test; real gh and real git drive the server in CI; a JSON differ compares responses against recorded github.com output field for field; and the suite runs against both SQLite and Postgres. The githome-conform tool certifies a running instance against the compatibility matrix as a black-box client and exits non-zero on any drift, so it can gate a release.

Design in one screen

  • One Go binary, githome, that serves the REST and GraphQL APIs, the git smart-HTTP transport, and the web UI. Two helpers ship beside it: githome-migrate runs the schema migrations, and githome-conform certifies a running instance against the compatibility matrix.
  • Postgres is the primary datastore; SQLite (pure Go, no cgo) is supported for small and single-node deployments. The same migrations run on both, and the server applies them on startup.
  • Git access is hybrid: go-git for cheap reads, the git binary for transport, merge, and diff.
  • One rule keeps the API surfaces from drifting apart: the REST, GraphQL, and web layers never touch the store or git directly. They all go through the domain layer for data and a presenter layer for rendering, so no surface can diverge from another or from GitHub.

There are no Go internal/ directories in this project on purpose; boundaries are enforced by the single-writer domain layer and by lint, not by the package system.

Install

Tagged releases ship as static binaries for Linux, macOS, Windows and the BSDs, as Linux packages (deb, rpm, apk), and as a multi-arch container image. The paths that work today:

docker pull ghcr.io/tamnd/githome:latest                # container
go install github.com/tamnd/githome/cmd/githome@latest  # from source

Every release also attaches prebuilt archives and deb/rpm/apk packages you can download and install directly. The pipeline additionally builds Homebrew, Scoop, winget, AUR and Nix entries; those go live once their taps are created and their tokens are set, which INSTALL.md walks through alongside every install method and the server configuration.

Run

The server reads its configuration from the environment and applies migrations on startup, so a single-node SQLite instance needs nothing but a few variables:

export GITHOME_DATABASE_URL="sqlite://githome.db"
export GITHOME_DATA_DIR="./data"
export GITHOME_HTML_BASE_URL="http://localhost:3000"
export GITHOME_SESSION_KEY="$(openssl rand -hex 32)"   # at least 32 bytes
export GITHOME_TOKEN_PEPPER="$(openssl rand -hex 32)"  # at least 16 bytes
githome

It listens on :3000 by default and serves the web UI, the REST API under /api/v3, GraphQL under /api/graphql, and the git smart-HTTP transport. Point gh and git at it:

export GH_HOST=localhost:3000
gh auth login --hostname localhost:3000
gh repo create myrepo --private
git clone http://localhost:3000/<you>/myrepo.git

Use a postgres:// DSN for multi-node or production deployments. Every variable, including the optional ones, is documented in INSTALL.md and in the packaged githome.env.

Build

Requires Go 1.26 or newer and a git binary on PATH.

make build          # build ./bin/githome and ./bin/githome-migrate
make test           # run the test suite (SQLite)
make test-postgres  # run it against a local Postgres (make pg-up first)
make lint           # golangci-lint v2
make gates          # the cross-cutting CI checks (no internal/, no leaked hosts)

License

Apache License 2.0. See LICENSE.

Directories

Path Synopsis
api
graphql
Package graphql implements Githome's GraphQL API v4.
Package graphql implements Githome's GraphQL API v4.
graphql/dataloader
Package dataloader provides a generic per-request batch loader.
Package dataloader provides a generic per-request batch loader.
rest
Package rest implements Githome's REST API v3.
Package rest implements Githome's REST API v3.
Package auth turns a raw HTTP credential into a normalized Actor and decides what that actor may do.
Package auth turns a raw HTTP credential into a normalized Actor and decides what that actor may do.
cmd
githome command
Command githome runs the Githome server.
Command githome runs the Githome server.
githome-conform command
Command githome-conform certifies a running Githome instance against the compatibility matrix: it points at a base URL with an auth token and a target repository, runs the section-3 surface (repository read, conditional requests, issue listing and pagination, the search endpoints, and GraphQL introspection plus a connection query), and prints a pass/fail report.
Command githome-conform certifies a running Githome instance against the compatibility matrix: it points at a base URL with an auth token and a target repository, runs the section-3 surface (repository read, conditional requests, issue listing and pagination, the search endpoints, and GraphQL introspection plus a connection query), and prints a pass/fail report.
githome-migrate command
Command githome-migrate applies or rolls back Githome's database migrations.
Command githome-migrate applies or rolls back Githome's database migrations.
githome-realworld-ingest command
Command githome-realworld-ingest runs the two-stage real-world corpus pipeline: Stage A exports public repository metadata and git history into a pinned, normalized snapshot, and Stage B seeds that snapshot into a target store.
Command githome-realworld-ingest runs the two-stage real-world corpus pipeline: Stage A exports public repository metadata and git history into a pinned, normalized snapshot, and Stage B seeds that snapshot into a target store.
Package config loads and validates Githome's runtime configuration from the environment (with an optional file overlay) into a single immutable Config.
Package config loads and validates Githome's runtime configuration from the environment (with an optional file overlay) into a single immutable Config.
Package conform certifies a Githome instance against the compatibility matrix.
Package conform certifies a Githome instance against the compatibility matrix.
Package domain holds Githome's business logic and value objects.
Package domain holds Githome's business logic and value objects.
Package etag computes deterministic HTTP entity tags for Githome responses.
Package etag computes deterministic HTTP entity tags for Githome responses.
fe
Package fe mounts the Githome web front: the human-facing, server-rendered HTML surface that sits beside the REST and GraphQL APIs in the same binary.
Package fe mounts the Githome web front: the human-facing, server-rendered HTML surface that sits beside the REST and GraphQL APIs in the same binary.
assets
Package assets owns the Githome web front's built static assets: the content-hashed CSS and JS bundles, the manifest that maps a logical name to its hashed file, and the Octicon icon registry the render layer inlines.
Package assets owns the Githome web front's built static assets: the content-hashed CSS and JS bundles, the manifest that maps a logical name to its hashed file, and the Octicon icon registry the render layer inlines.
assets/build command
Command build regenerates the embedded web-front bundle in fe/assets/dist.
Command build regenerates the embedded web-front bundle in fe/assets/dist.
render
Package render is the Githome web front's html/template engine.
Package render is the Githome web front's html/template engine.
route
Package route holds the Githome web front's URL-space rules: the reserved top-level names that a user or organization login may not take, and the ref-versus-path split that the tree and blob URLs need.
Package route holds the Githome web front's URL-space rules: the reserved top-level names that a user or organization login may not take, and the ref-versus-path split that the tree and blob URLs need.
view
Package view builds the view models the render layer turns into HTML.
Package view builds the view models the render layer turns into HTML.
web/auth
Package auth holds the Githome web front's authentication handlers: sign-in, sign-up, and sign-out.
Package auth holds the Githome web front's authentication handlers: sign-in, sign-up, and sign-out.
web/checks
Package checks holds the Githome web front's commit-checks surface: the page at /{owner}/{repo}/checks/{ref} that shows the status-check rollup for a ref, its check-run rows, and its commit-status rows.
Package checks holds the Githome web front's commit-checks surface: the page at /{owner}/{repo}/checks/{ref} that shows the status-check rollup for a ref, its check-run rows, and its commit-status rows.
web/compare
Package compare holds the Githome web front's branch-comparison handlers: the branch picker that starts a comparison, and the range view that shows the three-dot diff between two branches with an optional pull-request creation form.
Package compare holds the Githome web front's branch-comparison handlers: the branch picker that starts a comparison, and the range view that shows the three-dot diff between two branches with an optional pull-request creation form.
web/dashboard
Package dashboard holds the global, viewer-scoped lists at the reserved top-level /issues and /pulls names: the cross-repo "your issues" and "your pull requests" pages (spec doc 02 section 1.1, doc 09 section 1.6).
Package dashboard holds the global, viewer-scoped lists at the reserved top-level /issues and /pulls names: the cross-repo "your issues" and "your pull requests" pages (spec doc 02 section 1.1, doc 09 section 1.6).
web/home
Package home holds the Githome web front's landing surface: the root page at / and its named twin at /dashboard.
Package home holds the Githome web front's landing surface: the root page at / and its named twin at /dashboard.
web/issues
Package issues holds the Githome web front's issues handlers: the index with its search-and-filter bar, the detail page with its comment timeline and sidebar, the comment composer, the reactions, and the new-issue form.
Package issues holds the Githome web front's issues handlers: the index with its search-and-filter bar, the detail page with its comment timeline and sidebar, the comment composer, the reactions, and the new-issue form.
web/notifications
Package notifications holds the viewer-scoped notifications inbox at the reserved top-level /notifications name (spec doc 02 section 1.1).
Package notifications holds the viewer-scoped notifications inbox at the reserved top-level /notifications name (spec doc 02 section 1.1).
web/profile
Package profile holds the Githome web front's profile handlers: the user and organization overview at /{owner} and its repositories tab.
Package profile holds the Githome web front's profile handlers: the user and organization overview at /{owner} and its repositories tab.
web/pulls
Package pulls holds the Githome web front's pull-request handlers: the index with its state tabs, the PR shell the four tabs hang off, the Conversation timeline, the Commits tab, the read-only Files-changed diff, and the merge box with its poll fragment and merge mutation.
Package pulls holds the Githome web front's pull-request handlers: the index with its state tabs, the PR shell the four tabs hang off, the Conversation timeline, the Commits tab, the read-only Files-changed diff, and the merge box with its poll fragment and merge mutation.
web/repo
Package repo holds the Githome web front's code-browsing handlers: the repo home, the tree and blob views, the raw byte view, commit history, the branch and tag overviews, and the file finder.
Package repo holds the Githome web front's code-browsing handlers: the repo home, the tree and blob views, the raw byte view, commit history, the branch and tag overviews, and the file finder.
web/reposettings
Package reposettings holds the Githome web front's repository settings handlers.
Package reposettings holds the Githome web front's repository settings handlers.
web/search
Package search holds the Githome web front's search surface: the global /search page and the in-repo /{owner}/{repo}/search page.
Package search holds the Githome web front's search surface: the global /search page and the in-repo /{owner}/{repo}/search page.
web/settings
Package settings holds the Githome web front's account settings handlers.
Package settings holds the Githome web front's account settings handlers.
webmw
Package webmw holds the Githome web front's middleware: the signed session cookie that resolves the viewer, the color-mode cookie, the CSRF guard, the one-shot flash cookie, and the panic recovery that renders the HTML error page.
Package webmw holds the Githome web front's middleware: the signed session cookie that resolves the viewer, the color-mode cookie, the CSRF guard, the one-shot flash cookie, and the panic recovery that renders the HTML error page.
Package git is Githome's read access to the bare repositories on disk.
Package git is Githome's read access to the bare repositories on disk.
Package gittransport serves git clone and fetch over the Git Smart HTTP protocol.
Package gittransport serves git clone and fetch over the Git Smart HTTP protocol.
Package jsondiff makes "100% compatible with GitHub" mechanical.
Package jsondiff makes "100% compatible with GitHub" mechanical.
Package markup renders GitHub Flavored Markdown to sanitized, trusted HTML and highlights source code, for BOTH the web frontend and the REST text/html media type.
Package markup renders GitHub Flavored Markdown to sanitized, trusted HTML and highlights source code, for BOTH the web frontend and the REST text/html media type.
Package nodeid encodes and decodes the opaque identifiers Githome uses for the GraphQL `id` field and the REST `node_id` field.
Package nodeid encodes and decodes the opaque identifiers Githome uses for the GraphQL `id` field and the REST `node_id` field.
Package presenter renders domain values into the exact wire shapes GitHub emits.
Package presenter renders domain values into the exact wire shapes GitHub emits.
gqlmodel
Package gqlmodel holds the hand-written Go types that back Githome's GraphQL object types and scalars.
Package gqlmodel holds the hand-written Go types that back Githome's GraphQL object types and scalars.
restmodel
Package restmodel holds the exact JSON wire structs Githome serves on the REST API.
Package restmodel holds the exact JSON wire structs Githome serves on the REST API.
Package realworld is the real-world ingest subsystem: it exports the public metadata and git history of a handful of the largest GitHub-native repositories into a pinned, normalized corpus, then seeds that corpus into a Githome instance so the read, write, search, git, and event paths can be exercised at a scale the small development fixture never reaches.
Package realworld is the real-world ingest subsystem: it exports the public metadata and git history of a handful of the largest GitHub-native repositories into a pinned, normalized corpus, then seeds that corpus into a Githome instance so the read, write, search, git, and event paths can be exercised at a scale the small development fixture never reaches.
Package search parses GitHub's search query mini-language into the structured form the domain resolves and the store filters on.
Package search parses GitHub's search query mini-language into the structured form the domain resolves and the store filters on.
Package store is the single entry point to Githome's metadata database.
Package store is the single entry point to Githome's metadata database.
migrations
Package migrations holds Githome's embedded SQL schema migrations and exposes them as a read-only filesystem for the store's migration runner.
Package migrations holds Githome's embedded SQL schema migrations and exposes them as a read-only filesystem for the store's migration runner.
Package webhook delivers a repository's recorded events to its registered hooks.
Package webhook delivers a repository's recorded events to its registered hooks.
Package worker is the background job queue: the enqueue API job producers submit through, and (from a later milestone) the claim-and-run loop that drains it.
Package worker is the background job queue: the enqueue API job producers submit through, and (from a later milestone) the claim-and-run loop that drains it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL