No description
  • TypeScript 74%
  • Go 19.7%
  • HTML 2.3%
  • JavaScript 1.6%
  • Shell 1.2%
  • Other 0.8%
Find a file
gmackie a464bf2fee
Some checks failed
preflight-build / enqueue (push) Failing after 4s
CI / gitleaks (push) Successful in 11s
Restore ForgeGraf Control Plane / restore (push) Successful in 16s
CI / storybook (push) Successful in 1m50s
CI / web-build (push) Successful in 4m0s
Deploy ForgeGraf / test (push) Successful in 8m7s
forgegraph/ci CI passed
CI / ci (push) Successful in 14m28s
Deploy ForgeGraf / deploy (push) Successful in 15m35s
Merge pull request 'fix(agent): restore managed Worker deploy launchers and release 0.1.74' (#642) from fix-worker-deploy-launchers into main
2026-10-06 10:41:20 +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(ci): budget web typecheck heap without parallel fanout 2026-10-05 09:48:51 -04:00
.gitea docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
.github chore(agent): prepare signed 0.1.71 poll timeout recovery 2026-10-05 09:51:14 -04: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(agent): restore managed Worker deploy launchers and release 0.1.74 2026-10-06 06:26:06 -04:00
android feat(oauth): trust NetControl as an OIDC client (#17) 2026-07-06 14:05:52 -07:00
apps Merge pull request 'feat(api): push signed delivery events to Kanbanger' (#634) from feat/kanbanger-notifications into main 2026-10-05 18:29:55 +00:00
docs fix(ci-template): publish contracts with the env and binary the CLI uses 2026-10-05 22:50:43 -04:00
fixtures feat(ci): add mise-managed toolchains (#399) 2026-08-23 20:36:47 +00:00
infra fix(telemetry): filter trace identifiers before correlation aggregation 2026-10-05 12:30:14 -04:00
ios chore(ios): untrack ios/Pods, which .gitignore already excludes 2026-08-14 17:28:17 -04:00
npm fix(agent): restore managed Worker deploy launchers and release 0.1.74 2026-10-06 06:26:06 -04:00
ops fix(store-prune): root every store path a unit references, not just one 2026-09-13 23:49:25 -04:00
packages fix(api): deliver outbox notifications with redirect "manual" 2026-10-05 16:18:01 -04:00
plans merge: reconcile divergent main (land second #552 merge onto forge/main) 2026-09-09 16:22:25 -04:00
scripts fix(deploy): stop Corepack prompting on the runner's pty after a reboot 2026-09-13 22:33:19 -04:00
skills feat(fg): onboard Forge packages — forge.toml detection, config, CI scaffold 2026-10-01 01:31:05 -04:00
tooling fix: remediate system audit P0 P1 P2 findings 2026-09-06 19:49:41 -04:00
.dockerignore feat: add Dockerfile and production deployment config 2026-03-20 12:23:48 -07:00
.easignore feat(mobile): monitor PR delivery through production (#546) 2026-09-04 02:51:36 +00: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 chore(agent): package signed telemetry release 0.1.68 2026-09-16 17:34:11 -04:00
.gitleaks.toml ci(security): run gitleaks in CI to block committed secrets 2026-07-30 00:38:09 -05:00
.npmrc feat(web): consume @preflight/runreport core + web-run provider (Phase 6b) 2026-08-26 20:40:22 -04:00
.nvmrc chore: bump Node 22 → 24 across Dockerfile, .nvmrc, engines, CI templates 2026-05-06 05:38:04 -07:00
.oxlintrc.json feat(lint): make anti-slop a package instead of a per-repo copy 2026-08-17 22:11:53 -04:00
.worktreeinclude chore: add .worktreeinclude for jj workspace inheritance 2026-09-09 16:24:37 -04:00
AGENTS.md Land the unmerged branch backlog: targets, archived-target deploys, flake-backed jobs, sync preflight, fleet evidence (#578) 2026-09-15 20:23:41 +00:00
ARCHITECTURE.md fix: remediate system audit P0 P1 P2 findings 2026-09-06 19:49:41 -04:00
CHANGELOG.md fix(agent): restore managed Worker deploy launchers and release 0.1.74 2026-10-06 06:26:06 -04:00
CLAUDE.md docs(skills): add fg-migrate-d1 — Postgres→D1 migration wave skill 2026-08-26 14:29:37 -04: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: Forgejo is the source of truth, GitHub is a mirror (#464) 2026-08-26 18:12:32 +00: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 fix(deploy): make main deployable again after the contract package landed 2026-09-14 00:04:52 -04:00
LICENSE docs(community): OSS contribution strategy, CoC, and good-first issues 2026-07-11 10:41:19 -07:00
package.json fix: remediate system audit P0 P1 P2 findings 2026-09-06 19:49:41 -04:00
pnpm-lock.yaml chore(release): fg CLI 0.3.10 2026-10-01 22:09:49 +00:00
pnpm-workspace.yaml fix: remediate system audit P0 P1 P2 findings 2026-09-06 19:49:41 -04: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 Land the unmerged branch backlog: targets, archived-target deploys, flake-backed jobs, sync preflight, fleet evidence (#578) 2026-09-15 20:23:41 +00: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 fg — forge 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).