DEV Community

Cover image for Ghostty Leaves GitHub: What My Usage Logs Say About Devs' Real Dependency on Microsoft Platforms
Juan Torchia
Juan Torchia

Posted on • Originally published at juanchi.dev

Ghostty Leaves GitHub: What My Usage Logs Say About Devs' Real Dependency on Microsoft Platforms

Ghostty Leaves GitHub: What My Usage Logs Say About Devs' Real Dependency on Microsoft Platforms

Why do we keep calling it "the open source community" when it runs almost entirely on infrastructure owned by a company that paid $7.5 billion to buy that space? I've been asking myself that every time I do git push origin main and automatically trigger a GitHub Actions workflow, publish to GitHub Pages, cut a release on GitHub Releases, and wait for the GitHub issue tracker to notify someone. Everything on the same platform. Everything under the same Microsoft roof.

The r/programming thread about Ghostty leaving GitHub hit 1110 points and opened a conversation that most people shut down way too fast: "it's their choice," "GitHub is free for OSS anyway," "nobody's forcing them." Sure. And nobody forced anyone to put their whole head in the same bag for everything. That doesn't make it less risky.

Ghostty Leaving GitHub and Developer Dependency: The Real Map of the Problem

Mitchell Hashimoto — the guy who built Vagrant, Terraform, and Packer before founding HashiCorp — knows how to read an infrastructure dependency when he sees one. The decision to move Ghostty off GitHub isn't a philosophical tantrum. It's someone with enough history to recognize the pattern before it hurts.

My thesis is this: Ghostty isn't leaving GitHub. It's signaling that the entire open source software industry built its toolchain on someone else's land, and that has a cost that almost never shows up on productivity dashboards.

The problem isn't Microsoft. The problem is concentration. When a single platform simultaneously controls your version control, CI/CD, release distribution, issue tracking, public documentation, and project identity — that's not convenience. That's systemic dependency dressed up as convenience.

And I fell for it too. I went through my own logs this week to quantify it.

What My Logs Actually Say: How Much of My Stack Runs on GitHub

I have four active projects in production. A Next.js SaaS deployed on Railway, two TypeScript libraries, and a set of automation scripts I use internally. I went through them one by one.

# Script I used to audit GitHub dependency per repository
# Counts how many GitHub "surfaces" each project uses

#!/bin/bash
# audit-github-dependency.sh

REPO=$1

echo "=== Auditing GitHub dependency for: $REPO ==="

# Check GitHub Actions
if [ -d ".github/workflows" ]; then
  WORKFLOWS=$(ls .github/workflows/*.yml 2>/dev/null | wc -l)
  echo "[CI/CD] Active GitHub Actions: $WORKFLOWS workflows"
fi

# Check GitHub Pages
if git remote -v | grep -q "github.io\|gh-pages"; then
  echo "[DOCS] GitHub Pages: active"
fi

# Check references to GitHub Releases in scripts
RELEASE_REFS=$(grep -r "github.com/releases\|gh release\|GITHUB_TOKEN" . \
  --include="*.yml" --include="*.sh" --include="*.ts" | wc -l)
echo "[RELEASES] References to GitHub Releases: $RELEASE_REFS"

# Check dependencies downloaded from GitHub
GH_DEPS=$(grep -r "github.com" package.json package-lock.json 2>/dev/null | \
  grep -v "devDependencies\|homepage\|repository" | wc -l)
echo "[DEPS] Dependencies referencing GitHub: $GH_DEPS"

echo ""
echo "Total GitHub surface in this repo:"
echo "  CI: $WORKFLOWS workflows"
echo "  Releases: $RELEASE_REFS references"
echo "  External deps: $GH_DEPS"
Enter fullscreen mode Exit fullscreen mode

The actual results, no sugarcoating:

  • SaaS project (Next.js + Railway): 3 Actions workflows (deploy preview, lint, tests), releases published via gh release create, issues as the team's primary tracker. If GitHub goes down tomorrow or changes its Actions terms, the deploy pipeline stops cold.
  • TypeScript Library 1: CI on Actions, distributed via npm but the release tag that triggers the publish lives in GitHub Releases. Cross-dependency.
  • TypeScript Library 2: Identical. Plus GitHub Pages for the TypeDoc-generated documentation.
  • Internal scripts: No formal CI, but the README has GitHub badges and the third-party tool binaries I use get pulled from GitHub Releases.

Counting unique GitHub surfaces across my stack: CI/CD, releases, issues, pages, project identity (stars/forks as social signal), and OAuth authentication in a couple of integrations. Six surfaces. Six failure points concentrated in a single vendor.

When I saw it written out like that, I remembered a class back at UBA where someone explained what a single point of failure actually is. I'd come straight from work, still in my work clothes, and the professor drew a graph where one node connected everything. "If that node goes down, what happens?" The obvious answer. Apparently not so obvious when that node comes with a nice UI and free Actions for OSS projects.

The Most Common Mistakes When Evaluating This Dependency

Mistake 1: Confusing "free" with "no cost."
GitHub Actions has a generous free tier for OSS. That doesn't mean zero cost. The cost is lock-in: when you need something Actions doesn't handle well, or when GitHub changes the limits (it did in 2023 with Packages storage), migration isn't a sed -i. It's rewriting entire pipelines.

Mistake 2: Assuming the code in git is "outside" GitHub.
The code itself, yes. The workflows, the third-party GitHub Actions you use, the references to $GITHUB_TOKEN, the secrets configured in the UI — none of that moves with a git clone. I learned this the hard way when I tried to replicate a pipeline on a local runner for debugging: it took four hours to understand that three of my marketplace Actions had no portable equivalent.

Mistake 3: Underestimating the cost of migrating issues.
I ran the experiment last week. Exported the issues from one of my repos with the GitHub CLI:

# Export GitHub issues to JSON to audit migration cost
gh issue list --repo juanchi/my-project \
  --state all \
  --limit 1000 \
  --json number,title,body,labels,comments,createdAt \
  > issues-export.json

# See how many have comments with cross-references to PRs or commits
jq '[.[] | select(.comments > 0)] | length' issues-export.json
# Result: 47 of 89 issues have comments with references to PRs
# Those references are GitHub URLs. On another platform, they're dead text.
Enter fullscreen mode Exit fullscreen mode

47 of 89 issues with cross-linked context that becomes dead text on migration. Not insurmountable. But also not the one-click thing everyone imagines when they say "the code is portable anyway."

Mistake 4: Ignoring the social dependency.
Stars, forks, contributors — these are credibility signals in the ecosystem. If Ghostty migrates to Forgejo or Codeberg, it instantly loses that accumulated social signal. Not because the project got worse: because the ecosystem trained everyone to read those metrics on GitHub. That's also dependency. The quietest kind.

This kind of silent concentration is the same pattern I ran into when I simulated migrating my stack from OpenAI to Amazon Bedrock: the numbers look clean until you start counting the integration surfaces that never appear on the pricing page.

FAQ: Questions About Ghostty, GitHub, and Platform Dependency

Why did Ghostty specifically decide to leave GitHub?
Mitchell Hashimoto's public reasoning points to control over project infrastructure and not wanting to depend on a platform that can change its policies at any time. Ghostty has a particular development cadence — deliberate releases, a very curated community — and GitHub isn't neutral in how it presents and distributes that. The decision is consistent with who Hashimoto is: someone who built HashiCorp while watching up close how third-party infrastructure can become a business variable you don't control.

What real alternatives to GitHub exist for OSS?
The mature options are Forgejo (active Gitea fork, self-hosted), Codeberg (public Forgejo instance), GitLab (self-hosted or SaaS), and SourceHut (minimalist, no JavaScript in the frontend). Each has different tradeoffs. Codeberg is the most accessible for OSS projects that don't want to manage infrastructure. GitLab self-hosted is the most complete but also the most expensive to operate. None of them have GitHub's social network.

How long does it actually take to migrate an active project off GitHub?
Depends on integration depth. For a simple project with basic CI and few issues: a weekend. For a project with complex pipelines, marketplace Actions, GitHub Pages, automated Releases, and an active community in the issues: count on weeks of real work, plus the cost of communicating the change to everyone who has the repo as a reference. Cross-references in issues and PRs are the biggest pain — they don't migrate cleanly to any platform.

Is GitHub Actions replaceable without too much drama?
Technically yes: Woodpecker CI, Forgejo Actions (compatible with GitHub's syntax), GitLab CI/CD, and Drone are all viable. In practice, the marketplace Actions ecosystem — especially the third-party actions you use without thinking — doesn't have a direct equivalent everywhere. The YAML format is similar, but specific actions (actions/cache, actions/setup-node, cloud service integrations) need manual replacement. Not impossible. Just work nobody budgeted for.

Does this only apply to OSS projects or to company teams too?
It applies equally — or more — to company teams. In OSS, worst case you lose visibility and migration is painful but doable. In a corporate team that put everything in GitHub Enterprise — code, CI, issues, wikis, Dependabot, code scanning — a licensing decision or a Microsoft pricing change can become an operational risk event. As a Software Architect I evaluate this as part of system design: what happens if this vendor changes their terms tomorrow? If the answer is "catastrophe," that's an architecture problem, not just a tool preference.

Is it worth migrating if GitHub is still "free" for OSS?
The right question isn't whether it's worth migrating — it's what design decisions you make today that make migrating tomorrow harder or easier. You don't need to leave GitHub to reduce the dependency. You can: use self-hosted runners for critical CI, keep a mirror on another git host, document in a portable format (not GitHub Wiki), and avoid marketplace Actions that have no equivalent outside GitHub. Partial diversification is more realistic than full migration for most projects.

What I'd Do Differently: My Concrete Position

I'm not leaving GitHub tomorrow. It would be dishonest to say otherwise — I have active projects, a team working on that platform, and the migration cost doesn't justify itself right now. But Ghostty forced me to do something I hadn't done: audit the real surface area of my dependency and document it.

What I did change this week: I set up an automatic mirror to a self-hosted Forgejo instance on Railway for my two most critical repos. Not as a complete operational alternative, but as a migration muscle. Having the mirror in place forces me to keep my workflows less coupled to GitHub-specific APIs.

# Set up automatic mirror from GitHub to self-hosted Forgejo
# This goes in a GitHub Actions workflow (yes, the irony)

# .github/workflows/mirror-to-forgejo.yml
name: Mirror to Forgejo

on:
  push:
    branches: ['**']
  delete: {}

jobs:
  mirror:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history, not just last commit

      - name: Push to Forgejo mirror
        run: |
          # Use deploy key configured as a secret in GitHub
          git remote add forgejo-mirror \
            "https://${{ secrets.FORGEJO_USER }}:${{ secrets.FORGEJO_TOKEN }}@my-forgejo.railway.app/juanchi/${{ github.event.repository.name }}.git"
          git push forgejo-mirror --all --force
          git push forgejo-mirror --tags --force
Enter fullscreen mode Exit fullscreen mode

The workflow lives in GitHub Actions. It's paradoxical. But if tomorrow I need to invert the relationship — push from Forgejo and keep GitHub as the mirror — the setup already exists. The cost of that day drops from weeks to hours.

The uncomfortable part is that this conversation should've happened five years ago, not when a project with 1110 upvotes on r/programming puts it on the agenda. The same silent concentration I looked at when reviewing what happens when an agent deletes production applies here: the risk isn't the obvious catastrophic event, it's the dependency you normalized so thoroughly you stopped seeing it as a risk at all.

Ghostty isn't doing anything radical. It's doing what we all should've done: asking how much power we handed to a platform we don't control, and deciding with open eyes whether that tradeoff is worth it.

I decided the mirror is worth it. The full pipeline migration can wait. But the migration muscle, that can't.


Have you ever audited the real GitHub surface area in your projects? Whatever number you find will probably make you uncomfortable. Tell me in the comments or in the repo issues — yes, still on GitHub, for now.


This article was originally published on juanchi.dev

Top comments (0)