Help us shape the future of Go! Take the 2026 Go Developer Survey

shithub

module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: AGPL-3.0

README

shithub

A 1:1 reverse-engineering of GitHub. AGPLv3. Without Copilot.


Status: v0.1.0 launched — early days. Honest about WIP areas.

shithub is an attempt to recreate GitHub — the platform, the UI, the workflows — as faithfully as we can, as a self-hostable open-source forge. The goal is "you should barely notice you switched." We are not there yet. The core forge loop works end-to-end (see "What works today"); large surfaces (SSH transport, Actions/CI, GraphQL, Packages) are explicitly not shipped at v0.1.0.

The hosted instance is at shithub.sh. The project's own source has migrated here from GitHub; this GitHub repo is a one-way mirror for the first 90 days post-launch as a recovery surface.

If you came here expecting drop-in parity with everything GitHub does, you'll find specific gaps. If you came here for an honest, AI-free, self-hostable forge, this is for you.

What works today

The core forge loop works end-to-end against the codebase you're reading:

  • Identity — email/password signup, email verification, password reset, TOTP 2FA + recovery codes, SSH keys, personal access tokens (scoped), sessions.
  • Repositories — create, fork, archive, transfer, soft-delete with grace, rename with redirects, visibility toggles, branch protection (force-push / deletion / required reviews / required status checks), default-branch swap, topics, README/license/.gitignore templates.
  • Git — bare repos on disk; HTTPS smart-HTTP push/pull (SSH service is planned but not shipped yet); pre/post-receive hook integration for size accounting and event emission.
  • Code browsing — tree, blob (chroma syntax highlighting with light/dark themes), raw, blame, commit history, individual commit views, branch/tag listings, compare views, file finder.
  • Issues & PRs — full CRUD on issues + comments + labels + milestones + assignees; pull requests with diff rendering, file-by-file review, line comments, reviews (approve/request-changes/comment), required-reviewer enforcement, status-check gates, three merge methods (merge / squash / rebase), conflict detection.
  • Social — stars, watches with notification level, forks (clone-on-create), /explore, stargazer/watcher lists.
  • Search — code search (path + content, tantivy-equivalent indexing in Postgres), repo search, user search, quick-search.
  • Notifications — per-user inbox, email fan-out, watch-level routing, one-click HMAC-signed unsubscribe links, auto-subscribe on participation.
  • Organizations & teams — create, member roles (member/owner), invitations, one-level team nesting, team grants on repos with max-of-sources policy aggregation.
  • Repo settings — General (description, topics, features, merge methods), Access (collaborators + team grants), Branches (protection rules), Danger (rename/transfer/archive/visibility/delete).
  • Webhooks — outbound delivery with HMAC-SHA256 signing, exponential backoff with jitter, auto-disable on persistent failure, SSRF defense (DNS resolve + IP block-list + dial-the-IP transport, no redirect-following), redelivery UI, ping events.

What doesn't work yet

Pulled directly from the sprint plan we're working through:

  • SSH git service — HTTPS works; the SSH front-end is planned. Use HTTPS clone URLs for now.
  • Actions / CI — there is no CI runner. Status checks are wired into PR gates so a future runner can publish into them.
  • Packages, Pages, Projects, Releases, Gists — none of these surfaces exist yet.
  • GraphQL API — only the internal HTTP surface exists. There is no public REST or GraphQL API.
  • Activity feed — domain events are recorded but the activity-feed view isn't built.
  • Admin / site-admin surface — there is no /admin UI. Operator tooling is via shithubd subcommands and SQL.
  • Visual polish — most pages render correctly but do not look like GitHub yet. Spacing, typography, header/footer chrome, color tokens, octicon coverage, empty-state illustrations, focus states — all still drifting from Primer. Closing this gap is ongoing; expect rough edges page-to-page.
  • Mobile / responsive — the current CSS is desktop-first. Small viewports work but aren't tuned.
  • Deferred from completed sprints — every sprint spec lists "inbound deferrals" that landed and "outbound deferrals" that were pushed forward. See .docs/sprints/ for the running list.

Why

GitHub is a well-built platform. Microsoft's Copilot push has changed the product's character — particularly around how user code is treated as training data. shithub aims to recreate the parts that worked, on terms that make a self-hosted instance an honest equal to the SaaS experience, with AGPLv3 keeping any hosted variant open.

The "1:1" goal is intentional. There are plenty of git forges with their own UX vision; shithub deliberately doesn't try to be one of them. The closer the muscle-memory match, the lower the cost of switching.

Quickstart (development)

make dev          # hot-reload server on http://localhost:8080
make test         # run tests
make build        # build bin/shithubd
make ci           # full CI pipeline locally (mirrors GitHub Actions)
make dev-migrate  # apply DB migrations against $SHITHUB_DATABASE_URL

Requires:

  • Go 1.22+ (developed against 1.26)
  • PostgreSQL 13+
  • A local MinIO (or any S3-compatible store) for the storage tests — make storage-up brings one up via docker-compose.
  • golangci-lint, gofumpt, goimports, air, sqlc, goose (installed via go install per the Makefile or your package manager).

Copy .env.example to .env and fill in the database URL, session keys, and TOTP/webhook AEAD key.

Layout

cmd/shithubd/        # main entry: web, ssh, worker, migrate, storage, version
internal/auth/       # password, sessions, TOTP, PATs, SSH keys, policy/RBAC
internal/repos/      # repo lifecycle, git ops, branches, tags, diffs, forks
internal/issues/     # issues + comments + labels + milestones
internal/pulls/      # pull requests + reviews + merge orchestration
internal/orgs/       # orgs + teams + member roles + principals
internal/webhook/    # outbound delivery + SSRF defense + signing
internal/notif/      # inbox + email fan-out + watch-level routing
internal/search/     # code/repo/user search
internal/markdown/   # rendering + reference resolution (#N, @user, @org/team)
internal/web/        # HTTP handlers + html/template + middleware
internal/worker/     # Postgres-backed job queue + handlers
internal/migrationsfs/migrations/   # numbered SQL migrations (goose)
.docs/sprints/       # sprint specifications (S00–S49 + SR1)

Roadmap

The work is structured as 50 sprints (S00–S49, plus SR1 audit remediation). Roughly:

  • S00–S04 — scaffolding, DB baseline, web shell, observability, storage abstractions ✅
  • S05–S09 — identity (auth, 2FA, SSH keys, PATs, profiles) ✅
  • S10–S20 — repos, git protocols, code browsing, branches/tags, hooks ✅ (SSH service deferred)
  • S21–S25 — issues, pulls, reviews, status checks, markdown ✅
  • S26–S29 — social, forks, search, notifications ✅
  • S30–S33 — orgs, teams, repo settings, webhooks ✅ (current)
  • S34–S40 — site admin, security hardening, federation, polish, accessibility, i18n
  • S41–S49 — actions/CI, social feed, advanced search, GraphQL API, packages, pages, projects, releases, gists

See .docs/sprints/ for the per-sprint spec.

Contributing

See CONTRIBUTING.md. The project is in active rapid development — substantial PRs are best discussed in an issue first so we don't both write the same code. Small fixes, doc improvements, and bug reports are welcome any time.

Security

To report a security issue, see SECURITY.md. Please do not open a public issue for security reports.

License

AGPLv3. If you run a modified version as a network service, your users are entitled to the source.

Directories

Path Synopsis
Command bench runs HTTP latency scenarios against a target shithub instance and emits one JSON record per scenario to stdout.
Command bench runs HTTP latency scenarios against a target shithub instance and emits one JSON record per scenario to stdout.
cmd
shithubd command
Command shithubd is the entrypoint binary for shithub.
Command shithubd is the entrypoint binary for shithub.
internal
auth
Package auth contains shared auth primitives used across the auth surface (handlers, middleware, services).
Package auth contains shared auth primitives used across the auth surface (handlers, middleware, services).
auth/audit
Package audit writes structured rows into the auth_audit_log table for security-relevant events.
Package audit writes structured rows into the auth_audit_log table for security-relevant events.
auth/email
Package email is the transactional-email layer for the auth surface.
Package email is the transactional-email layer for the auth surface.
auth/password
Package password implements argon2id password hashing with PHC-string encoding.
Package password implements argon2id password hashing with PHC-string encoding.
auth/pat
Package pat owns personal-access-token minting, hashing, scope constants, and the auth-middleware verification path.
Package pat owns personal-access-token minting, hashing, scope constants, and the auth-middleware verification path.
auth/policy
Package policy is the single source of truth for "who can do what".
Package policy is the single source of truth for "who can do what".
auth/secretbox
Package secretbox is a thin AEAD wrapper used to protect at-rest secrets — currently TOTP secrets, future sprints will reuse it for per-user key material (PATs, deploy keys, etc.).
Package secretbox is a thin AEAD wrapper used to protect at-rest secrets — currently TOTP secrets, future sprints will reuse it for per-user key material (PATs, deploy keys, etc.).
auth/session
Package session owns the cookie-based session pipeline.
Package session owns the cookie-based session pipeline.
auth/sshkey
Package sshkey wraps the parsing, validation, and fingerprinting of user-supplied SSH public keys.
Package sshkey wraps the parsing, validation, and fingerprinting of user-supplied SSH public keys.
auth/throttle
Package throttle implements counter-based rate limiting for the auth surface, backed by the auth_throttle table.
Package throttle implements counter-based rate limiting for the auth surface, backed by the auth_throttle table.
auth/token
Package token mints high-entropy random tokens and stores their sha256 hashes.
Package token mints high-entropy random tokens and stores their sha256 hashes.
auth/totp
Package totp implements RFC 6238 TOTP (time-based one-time password) enrollment and verification.
Package totp implements RFC 6238 TOTP (time-based one-time password) enrollment and verification.
avatars
Package avatars owns avatar resolution for shithub user profiles.
Package avatars owns avatar resolution for shithub user profiles.
cache/lru
Package lru is an in-process least-recently-used cache with optional TTL + singleflight wrapping.
Package lru is an in-process least-recently-used cache with optional TTL + singleflight wrapping.
checks
Package checks owns CI check-suite + check-run orchestration.
Package checks owns CI check-suite + check-run orchestration.
git/hooks
Package hooks owns the bare-repo hook installation contract used by the push pipeline (S14).
Package hooks owns the bare-repo hook installation contract used by the push pipeline (S14).
git/protocol
Package protocol carries the smart-HTTP and (later) smart-SSH bits of the git wire protocol that we generate ourselves.
Package protocol carries the smart-HTTP and (later) smart-SSH bits of the git wire protocol that we generate ourselves.
infra/config
Package config owns the layered configuration loader.
Package config owns the layered configuration loader.
infra/db
Package db owns the Postgres connection lifecycle.
Package db owns the Postgres connection lifecycle.
infra/errrep
Package errrep wires the Sentry-protocol-compatible error reporter.
Package errrep wires the Sentry-protocol-compatible error reporter.
infra/log
Package log builds the slog handler the rest of the binary uses.
Package log builds the slog handler the rest of the binary uses.
infra/metrics
Package metrics owns the Prometheus registry.
Package metrics owns the Prometheus registry.
infra/storage
Package storage provides shithub's storage abstractions:
Package storage provides shithub's storage abstractions:
infra/tracing
Package tracing wires the OpenTelemetry SDK and exposes a small HTTP-middleware helper.
Package tracing wires the OpenTelemetry SDK and exposes a small HTTP-middleware helper.
issues
Package issues owns the issue + comment + label + milestone domain logic.
Package issues owns the issue + comment + label + milestone domain logic.
markdown
Package markdown is shithub's canonical markdown rendering pipeline.
Package markdown is shithub's canonical markdown rendering pipeline.
markdown/extensions
Package extensions hosts the AST transformer that adds shithub- specific inline patterns (`@user`, `#N`, `owner/repo#N`, commit SHAs, emoji shortcodes) to Goldmark's parsed text without ever touching the contents of code blocks or inline code.
Package extensions hosts the AST transformer that adds shithub- specific inline patterns (`@user`, `#N`, `owner/repo#N`, commit SHAs, emoji shortcodes) to Goldmark's parsed text without ever touching the contents of code blocks or inline code.
migrationsfs
Package migrationsfs embeds the SQL migrations from the repo root and registers them with the db package.
Package migrationsfs embeds the SQL migrations from the repo root and registers them with the db package.
notif
Package notif owns S29's notification fan-out: consume from `domain_events`, compute the recipient set per the routing matrix, materialize inbox rows + email-side dispatch.
Package notif owns S29's notification fan-out: consume from `domain_events`, compute the recipient set per the routing matrix, materialize inbox rows + email-side dispatch.
orgs
Package orgs owns the organization domain: create, members, invitations, suspend/restore, soft-delete, and the principals resolver that unifies /{slug} routing across users + orgs.
Package orgs owns the organization domain: create, members, invitations, suspend/restore, soft-delete, and the principals resolver that unifies /{slug} routing across users + orgs.
pagination/keyset
Package keyset implements opaque keyset-pagination cursors.
Package keyset implements opaque keyset-pagination cursors.
passwords
Package passwords exposes the embedded common-password blocklist used at signup and password-reset to reject the most-prevalent passwords.
Package passwords exposes the embedded common-password blocklist used at signup and password-reset to reject the most-prevalent passwords.
pulls
Package pulls owns the pull-request orchestrator.
Package pulls owns the pull-request orchestrator.
pulls/review
Package review owns PR-review orchestration: inline comments, review submission with attached pending comments, dismissal, reviewer requests, thread resolution, and the required-reviews gate consulted by the merge handler.
Package review owns PR-review orchestration: inline comments, review submission with attached pending comments, dismissal, reviewer requests, thread resolution, and the required-reviews gate consulted by the merge handler.
ratelimit
Package ratelimit owns the cross-surface counter used by S35's rate-limit middleware.
Package ratelimit owns the cross-surface counter used by S35's rate-limit middleware.
repos
Package repos owns repository creation, validation, and identity.
Package repos owns repository creation, validation, and identity.
repos/diff/parse
Package parse wraps go-gitdiff.
Package parse wraps go-gitdiff.
repos/diff/render
Package render produces HTML for parsed diffs.
Package render produces HTML for parsed diffs.
repos/diff/source
Package source produces raw git-diff patch bytes for the parser.
Package source produces raw git-diff patch bytes for the parser.
repos/finder
Package finder implements the "Go to file" fuzzy match used by the /find/{ref} endpoint.
Package finder implements the "Go to file" fuzzy match used by the /find/{ref} endpoint.
repos/fork
Package fork owns S27's fork orchestration.
Package fork owns S27's fork orchestration.
repos/git
Package git wraps the git plumbing commands we need to build the optional initial commit on a freshly-init'd bare repo.
Package git wraps the git plumbing commands we need to build the optional initial commit on a freshly-init'd bare repo.
repos/highlight
Package highlight wraps Chroma so the rest of the project doesn't import it directly.
Package highlight wraps Chroma so the rest of the project doesn't import it directly.
repos/identity
Package identity resolves a commit author's email to a shithub user.
Package identity resolves a commit author's email to a shithub user.
repos/lifecycle
Package lifecycle owns the post-creation mutations of a repo: rename, transfer, archive/unarchive, visibility flip, soft-delete, restore, and hard-delete.
Package lifecycle owns the post-creation mutations of a repo: rename, transfer, archive/unarchive, visibility flip, soft-delete, restore, and hard-delete.
repos/protection
Package protection enforces branch-protection rules on incoming pushes.
Package protection enforces branch-protection rules on incoming pushes.
repos/templates
Package templates embeds the curated set of license, gitignore, and README templates offered by the repo-creation form.
Package templates embeds the curated set of license, gitignore, and README templates offered by the repo-creation form.
search
Package search owns S28's search surface.
Package search owns S28's search surface.
security/openredirect
Package openredirect validates `next=` style redirect targets so a crafted query parameter can't bounce a logged-in user off-host (the canonical phishing primitive).
Package openredirect validates `next=` style redirect targets so a crafted query parameter can't bounce a logged-in user off-host (the canonical phishing primitive).
security/ssrf
Package ssrf is the canonical SSRF-defense layer (S35).
Package ssrf is the canonical SSRF-defense layer (S35).
social
Package social owns S26's stars / watches / events surface.
Package social owns S26's stars / watches / events surface.
testing/dbtest
Package dbtest provides a parallel-safe test database harness.
Package dbtest provides a parallel-safe test database harness.
version
Package version exposes build-time information embedded via -ldflags.
Package version exposes build-time information embedded via -ldflags.
web
Package web boots the shithub HTTP server.
Package web boots the shithub HTTP server.
web/handlers
Package handlers registers HTTP handlers on the web server's mux.
Package handlers registers HTTP handlers on the web server's mux.
web/handlers/admin
Package admin owns the /admin/* surface — the operator dashboard for users/orgs/repos/jobs/audit/system management.
Package admin owns the /admin/* surface — the operator dashboard for users/orgs/repos/jobs/audit/system management.
web/handlers/api
Package api owns shithub's PAT-authenticated HTTP API surface.
Package api owns shithub's PAT-authenticated HTTP API surface.
web/handlers/auth
Package auth wires the email/password auth handlers (signup, login, logout, password reset, email verification) onto the chi router.
Package auth wires the email/password auth handlers (signup, login, logout, password reset, email verification) onto the chi router.
web/handlers/githttp
Package githttp wires the smart-HTTP git protocol routes: info/refs + git-upload-pack + git-receive-pack.
Package githttp wires the smart-HTTP git protocol routes: info/refs + git-upload-pack + git-receive-pack.
web/handlers/notifications
Package notifications wires the S29 notification web surface:
Package notifications wires the S29 notification web surface:
web/handlers/orgs
Package orgs wires the S30 organization web surface:
Package orgs wires the S30 organization web surface:
web/handlers/profile
Package profile owns the read-only public profile handlers: /{username} and /avatars/{username}.
Package profile owns the read-only public profile handlers: /{username} and /avatars/{username}.
web/handlers/repo
Package repo wires the HTTP handlers for repository creation and the (placeholder) repo home page.
Package repo wires the HTTP handlers for repository creation and the (placeholder) repo home page.
web/handlers/search
Package search wires the S28 web search surface.
Package search wires the S28 web search surface.
web/middleware
Package middleware provides shithub's HTTP middleware stack.
Package middleware provides shithub's HTTP middleware stack.
web/render
Package render owns the html/template loading and rendering pipeline.
Package render owns the html/template loading and rendering pipeline.
worker
Package worker drives the Postgres-backed job queue introduced in S14.
Package worker drives the Postgres-backed job queue introduced in S14.
worker/jobs
Package jobs holds the concrete worker handlers wired into the pool at boot.
Package jobs holds the concrete worker handlers wired into the pool at boot.

Jump to

Keyboard shortcuts

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