No description
  • TypeScript 76.9%
  • Go 17.4%
  • HTML 1.7%
  • Shell 1.4%
  • JavaScript 0.8%
  • Other 1.6%
Find a file
gmackie abfcfa73d1
All checks were successful
preflight-build / enqueue (push) Successful in 2s
CI / gitleaks (push) Successful in 8s
Deploy ForgeGraf / test (push) Successful in 2m56s
Deploy ForgeGraf / deploy (push) Successful in 4m6s
forgegraph/ci CI passed
CI / ci (push) Successful in 7m56s
fix(public-feed): select latest deployment attempt
Use one latest deployment per app ordered by attempt creation time so live project updates cannot be masked by older null deployment timestamps.
2026-08-06 20:16:50 +00:00
.agents/skills/react-doctor feat: DB-driven public feed overlays and API fixes (#3) 2026-05-12 18:42:38 -07:00
.bob/skills/react-doctor feat: DB-driven public feed overlays and API fixes (#3) 2026-05-12 18:42:38 -07:00
.claude feat(ci): CI & runner monitoring — capacity view, live Actions CI, thin alerting (#3) 2026-06-05 05:15:12 +00:00
.forge/workflows feat(registry): proactive dependency tracking, upstream monitor, and deploy trust gate 2026-06-22 11:25:16 -07:00
.forgejo fix(deploy): raise bounded OpenNext heap 2026-08-06 15:46:46 -04:00
.gitea docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
.github ci: disable unused GitHub Actions deployment workflow 2026-07-11 11:36:36 -07:00
.kiro/skills/react-doctor feat: DB-driven public feed overlays and API fixes (#3) 2026-05-12 18:42:38 -07:00
agent fix(hub): remove legacy command credentials 2026-08-05 07:57:04 -04:00
android feat(oauth): trust NetControl as an OIDC client (#17) 2026-07-06 14:05:52 -07:00
apps fix(public-feed): select latest deployment attempt 2026-08-06 16:08:22 -04:00
docs feat(public-feed): automate approved promotion scaffolds 2026-08-05 18:06:01 -04:00
infra docs: DNS-only route design and promtail install script 2026-05-17 17:39:02 -07:00
ios feat(oauth): trust NetControl as an OIDC client (#17) 2026-07-06 14:05:52 -07:00
npm fix(release): make 0.1.42 wrapper bins linkable 2026-08-03 03:10:22 -04:00
ops/ci-runners ci(distribute): make per-job container caps reproducible + fix README 2026-08-02 21:07:14 -04:00
packages test(ci): isolate database-backed API fixtures 2026-08-06 15:25:48 -04:00
patches fix(deps): upgrade next, better-auth, and override minimatch for security 2026-05-17 17:45:32 -07:00
plans docs(plans): mark quarantine + db:generate discoveries RESOLVED 2026-06-17 16:39:31 -04:00
scripts feat(content): acknowledge materialized promotion drafts 2026-08-05 20:09:42 -04:00
skills feat(cli): gate deploys on green CI with polling 2026-07-17 12:58:27 -07:00
tooling fix(tests): update stale test expectations and pin plugin-react < 6 2026-05-20 04:16:39 -07:00
.dockerignore feat: add Dockerfile and production deployment config 2026-03-20 12:23:48 -07:00
.env.example docs: bring TODOS.md and env examples up to reality (#86) 2026-07-12 17:13:52 +00:00
.env.production.example refactor(public-feed): retire data.gmac.io, reframe as workspace-specific 2026-04-20 16:45:00 -07:00
.forgegraph.yaml fix(deploy): configure public capture through current CLI 2026-08-05 04:30:29 -04:00
.gitignore merge: reconcile active ForgeGraph heads (4-way) — resolve 54 conflicts 2026-07-20 11:31:38 -07:00
.gitleaks.toml ci(security): run gitleaks in CI to block committed secrets 2026-07-30 00:38:09 -05:00
.npmrc ci(build): node-linker=hoisted so RN/Expo build scripts resolve under pnpm 2026-06-27 16:29:59 +00:00
.nvmrc chore: bump Node 22 → 24 across Dockerfile, .nvmrc, engines, CI templates 2026-05-06 05:38:04 -07:00
AGENTS.md docs: add Preflight CLI build/validate guide for agents (#36) 2026-07-01 08:34:31 +00:00
ARCHITECTURE.md feat(design-system): ship Storybook-backed design system + WIP rollup 2026-04-20 16:45:00 -07:00
CHANGELOG.md docs: refresh the CHANGELOG and state the release model 2026-07-29 23:53:33 -05:00
CLAUDE.md docs: update repo browser roadmap with shipped status 2026-04-20 16:44:28 -07:00
CODE_OF_CONDUCT.md docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
CONTEXT.md docs: add ADRs, design plans, and contract specifications 2026-05-27 00:33:00 -07:00
CONTRIBUTING.md docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
DESIGN.md feat(ui): add dark mode to web dashboard and landing page 2026-07-11 10:41:19 -07:00
docker-compose.prod.yml feat: add Dockerfile and production deployment config 2026-03-20 12:23:48 -07:00
docker-compose.yml feat(db): switch to local Postgres via Docker, generate initial migration 2026-03-19 14:41:31 -07:00
Dockerfile chore: bump Node 22 → 24 across Dockerfile, .nvmrc, engines, CI templates 2026-05-06 05:38:04 -07:00
FAB_DESIGN.md docs: add ADRs, design plans, and contract specifications 2026-05-27 00:33:00 -07:00
flake.lock feat: add Nix flake for ForgeGraph closure build 2026-03-22 13:51:47 -07:00
flake.nix feat(agent): add self-update watchdog rollback 2026-07-11 10:42:10 -07:00
LICENSE docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
package.json fix(release): make 0.1.42 wrapper bins linkable 2026-08-03 03:10:22 -04:00
pnpm-lock.yaml merge: land reconcile-heads integration work on current main 2026-07-20 17:02:24 -07:00
pnpm-workspace.yaml fix(nix): pnpm deploy with injectWorkspacePackages for registry deps 2026-06-27 08:50:03 -07:00
README.md docs: add screenshots of the running app to the README 2026-07-29 00:59:54 -05:00
SECURITY.md docs: add SECURITY.md and a docs/ index 2026-07-28 15:53:07 -05:00
STAGES.md updates 2026-06-13 12:04:35 -05:00
TODOS.md fix(mobile): clear all React Compiler hooks lint warnings 2026-07-22 13:43:48 -07:00
turbo.json fix(test): serialize shared-db test packages 2026-06-21 17:54:59 -04:00

ForgeGraph

Your delivery graph, not your deployment log.

License: MIT Agent: Go Deploys: Nix

Live instance: forgegraf.com — the control plane runs on Cloudflare Workers and orchestrates a fleet of Hetzner and homelab nodes. It deploys itself: every commit to main ships through the pipeline described below.

ForgeGraph landing page

The full landing page and the documentation site — both served by the app in this repo.

ForgeGraph is a Nix-native delivery and configuration platform. It tracks work items, changesets, and runtime evidence from first draft through production with real evidence — builds, tests, coverage, deployments, health checks, and alerts — all linked by stable work and changeset identity.

Built on Jujutsu's changeset model. Deploys Nix closures. No Docker. No Kubernetes. No YAML.

A self-hosted, Nix-native PaaS for indie hackers and small teams escaping cloud rent — see Positioning for the one-liner, category, differentiation pillars, and who it's not for. ⚠️ Early prototype: the delivery graph and Nix deploys work today; multi-tenancy, billing, and fleet scale are early.

Who is it for? See the Target Segments & ICP Playbook and market positioning — indie developers and small teams shipping web services on machines they own.

Quick Start

1. Bootstrap a node

curl -fsSL https://forgegraf.com/bootstrap | sudo sh

Installs the ForgeGraph agent on any Linux machine with Nix and systemd (Ubuntu, Debian, NixOS). The agent dials outbound only — no inbound ports, no SSH keys held by the control plane.

2. Install the CLI

npm install -g @forgegraph/cli
forge login --server https://forgegraf.com --token YOUR_TOKEN

Or via Nix:

nix run github:gmackorg/ForgeGraph#cli -- login --server https://forgegraf.com

The binary installs as both forge and fgforge is the preferred name, fg is kept as an alias for older muscle memory.

3. Deploy

forge deploy create production

Point --server at your own instance if you self-host instead of using forgegraf.com.

See docs/forge-cli.md for the full CLI reference, including forge db list, forge db url, and forge db connect for reaching managed Postgres databases over Tailscale.

Running in production

This is a working system, not a demo. The instance at forgegraf.com currently runs:

Fleet 6 registered nodes — 4 Hetzner VPS + 2 homelab machines, meshed over Tailscale
Apps 68 registered, 298 active deployments
History 666 deployments and 2,656 builds since the first deploy on 2026-05-02
Self-hosting ForgeGraph deploys itself: merges to main ship through its own pipeline
Also self-hosted its Git server (Forgejo), npm registry (Verdaccio + scanning), and Postgres

It is also its own worst customer — the platform runs the apps that report the bugs that drive the roadmap. Several of the incidents in field reports were found because ForgeGraph broke ForgeGraph.

Features

  • Work graph — canonical work items, planning artifacts, and task/decomposition relationships
  • Changeset tracking — JJ-native identity that persists through rebases, amendments, and force-pushes
  • Delivery evidence — builds, tests, coverage, artifacts, deployments as an append-only graph
  • Release gates — evidence-based promotion through staging, canary, production
  • Nix deployments — pre-built closures distributed via binary cache, deployed in seconds
  • NixOS configuration — visual editor for NixOS system configs with drift detection
  • Fleet management — interactive topology view, rolling updates, blue-green deployments
  • Real observability — Prometheus metrics, Loki logs, Grafana dashboards
  • Alerting — configurable alert rules with Slack/Discord/webhook notifications
  • Teams & billing — multi-user with Free/Pro/Enterprise tiers
  • Security — AES-256-GCM secret encryption, constant-time token verification

Architecture

The control plane is a Cloudflare Worker. It never connects into your machines: each node runs a small Go agent that polls outbound over HTTPS and holds a WebSocket to the hub for dispatch. That inversion is the core security property — your servers need no inbound ports and the platform holds no SSH keys.

flowchart TB
    subgraph cp["Control plane — hosted (Cloudflare Workers)"]
        web["Next.js app + tRPC API<br/>forgegraf.com"]
        hub["WebSocket hub<br/>ws.forgegraf.com"]
        pg[("Postgres<br/>via Hyperdrive tunnel")]
        web <--> pg
        hub <--> pg
    end

    subgraph src["Source of truth — also self-hosted"]
        forgejo["Forgejo<br/>git.forgegraf.com"]
        registry["npm registry<br/>Verdaccio + scanning"]
    end

    subgraph fleet["Your machines — you own these"]
        agent["forgegraph-agent (Go, stdlib only)"]
        subgraph sandbox["Per-app sandbox"]
            netns["network namespace<br/>veth + DNAT ingress"]
            nft["nftables egress policy<br/>default-deny"]
            unit["systemd unit<br/>bwrap + Nix closure"]
        end
        agent --> netns
        agent --> nft
        agent --> unit
    end

    web -->|"deploy / job / CI dispatch"| hub
    agent -.->|"outbound poll + WebSocket<br/>no inbound ports"| hub
    agent -->|"health, metrics, deploy evidence"| web
    forgejo -->|"webhooks: push, PR, merge"| web
    agent -->|"clone + build Nix closure"| forgejo
    agent -->|"publish / consume packages"| registry

Deployment targets. Web apps deploy to Cloudflare Workers; long-running services (Go binaries, workers, bots) deploy to fleet nodes as Nix closures activated by systemd. Both paths report the same evidence back into the delivery graph.

What the agent does on a node: allocates an IP and network namespace per app, wires ingress DNAT (including the hairpin rule for a colocated edge proxy), loads a default-deny nftables egress policy, writes and enables the systemd unit, runs migrations, health-checks, and rolls back on failure. It persists each sandbox's runtime spec to disk so a node reboot reconstructs namespaces, firewall rules, and services without the control plane being reachable.

Engineering notes

Start here: Engineering notes — a written case study of the seven problems that were genuinely hard, what the diagnosis actually looked like, and what changed as a result. Most of them share a shape: the system reported success while doing nothing.

The rest of the written record:

A few problems worth reading about, because the diagnosis was harder than the fix: an nftables egress policy that loaded into the host namespace instead of the app's and silently broke outbound traffic on the node; a colocated edge proxy whose requests bypassed PREROUTING and so never hit the sandbox until a hairpin DNAT rule was added; and a Go net/http upload that stalled against the Cloudflare edge purely as a function of body size, found with GODEBUG=http2debug=1 against the live agent after isolated reproductions all passed.

Install from Nix

{
  inputs.forgegraph.url = "github:gmackorg/ForgeGraph";

  # The agent
  environment.systemPackages = [ inputs.forgegraph.packages.${system}.agent ];

  # The CLI
  environment.systemPackages = [ inputs.forgegraph.packages.${system}.cli ];
  # Backward-compatible alias: inputs.forgegraph.packages.${system}.fg

  # ForgeGraph as a NixOS service
  imports = [ inputs.forgegraph.nixosModules.default ];
  services.forgegraph = {
    enable = true;
    environmentFile = "/etc/forgegraph/env";
    agent.enable = true;
    agent.environmentFile = "/etc/forgegraph/agent.json";
  };
}

Development

pnpm install    # Install dependencies
pnpm dev        # Start development server
pnpm build      # Production build

cd agent && go build -o forgegraph-agent ./...  # Build agent
cd agent && go build -o fg ./cmd/fg             # Build CLI (fg)

Contributing

ForgeGraph is early-stage open source (MIT). We want contributors, but we are still hardening reliability — community process is intentional and lightweight.

Primary community surface is the issue tracker (and Discussions when enabled). There is no public Discord/Slack yet — that is deliberate for a small maintainer team.

Stack

Component Technology
Web Next.js 16, React 19, Tailwind CSS 4
API tRPC, Drizzle ORM, PostgreSQL 17
Agent Go 1.25 (stdlib only, no third-party deps)
Deploy Nix flakes, systemd
Monitor Prometheus, Loki, Grafana
Design Newsreader, Public Sans, IBM Plex Mono

GTM / positioning

License

MIT — see also license tradeoffs and relicense guidance in docs/community/strategy.md (pending legal skim).